这里是一个让你为所欲为,欲罢不能的抽奖demo
寒暄
抽奖系统有很多,各式各样的,不知道大伙都抽中过什么,还是像我这样经历了绝望,看破红尘,存起来留给下一代。
这种抽奖场景在活动中很常见,为了更好的摸鱼,决定自己去写一个插件来解决重复劳动。接下来为大伙介绍一个不错的宫格抽奖组件,请看官往下挪步
关于grid-roll
grid-roll是一个vue的宫格组件,它让ui和逻辑分离,封装了逻辑和宫格布局,让开发者只关注奖品和按钮的ui部分。
- 自定义宫格数量,经典的3x3还是10x100都不在话下
- 多抽功能,一次点击多次抽奖,谷底梭哈,就问你刺不刺激
安装
npm i grid-roll -S
yarn add grid-roll
引入
/** 引入 */
import { gridRoll, gridStart, gridPrize } from 'grid-roll'
import 'grid-roll/dist/grid-roll.min.css'
实践
通过vuecli搭起新项目,这边我们可以直接用掘金抽奖的图片链接,拿过来吧你。
图片上的奖品我都打上了数字记号,这些记号其实就奖品数组的下标,它们对应着奖品位置,布局从左到右一行一行排列,所以我们的奖品数组元素排序要注意下
通过使用grid-roll,我们只需要定义里面8个奖品和1个按钮的样式就行,用gridStart和gridPrize去包装这些物料,塞进gridRoll里面,gridRoll会帮我们自动调整成九宫格布局。这里,我更喜欢把奖品写成数据去循环生成gridPrize。然后样式布局基本是打开开发者工具复制掘金的样式,所以就不细说了
介绍下这3个组件:
- gridRoll:interval这个属性用来定义宫格之前的间隔,默认是没有间隔的,这里我看感觉定义了6px。并且接受两个插槽button和prize
- gridStart:专门用来做button插槽的组件
- gridPrize:专门用来做prize插槽的组件
// 这里引入组件和样式
import { gridRoll, gridStart, gridPrize } from "grid-roll";
import "grid-roll/dist/grid-roll.min.css";
expoet default {
data () {
return {
prizes: [
{
id: 1,
text: "66矿石",
img: "https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/32ed6a7619934144882d841761b63d3c~tplv-k3u1fbpfcp-no-mark:0:0:0:0.awebp",
},
{
id: 2,
text: "随机限量徽章",
img: "https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/71c68de6368548bd9bd6c8888542f911~tplv-k3u1fbpfcp-no-mark:0:0:0:0.awebp",
},
{
id: 3,
text: "掘金新款T恤",
img: "https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5bf91038a6384fc3927dee294a38006b~tplv-k3u1fbpfcp-no-mark:0:0:0:0.awebp",
},
{
id: 4,
text: "Bug",
img: "https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0a4ce25d48b8405cbf5444b6195928d4~tplv-k3u1fbpfcp-no-mark:0:0:0:0.awebp",
},
{
id: 5,
text: "再抽2次解锁",
img: "https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/aabe49b0d5c741fa8d92ff94cd17cb90~tplv-k3u1fbpfcp-no-mark:0:0:0:0.awebp",
},
{
id: 6,
text: "掘金限量桌垫",
img: "https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c78f363f41a741ffa11dcc8a92b72407~tplv-k3u1fbpfcp-no-mark:0:0:0:0.awebp",
},
{
id: 7,
text: "Yoyo抱枕",
img: "https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/33f4d465a6a9462f9b1b19b3104c8f91~tplv-k3u1fbpfcp-no-mark:0:0:0:0.awebp",
},
{
id: 8,
text: "再抽3次解锁",
img: "https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4decbd721b2b48098a1ecf879cfca677~tplv-k3u1fbpfcp-no-mark:0:0:0:0.awebp",
},
],
}
}
components: {
gridRoll,
gridStart,
gridPrize,
},
}
从上面可以看到,我们只需要通过gridStart和gridPrize定义好按钮和奖品的样式,放进gridRoll就行,不用再去管其他乱七八糟的操作。
disabled的使用
从官方的图看起来,这边还缺少一个“锁”样式,需要通过抽奖次数进行解锁,除了奖品样式的不同,在滚动的时候还会直接跳过未解锁的奖品。这边gridPrize也有一个对应的prop做这件事。
首先在prizes需要用到“锁”的元素中添加一个字段disabled: true,传给gridPrize,当抽奖开始的时候,滚动会直接跳过disabled为true的奖品,其次我们用disabled来做一些样式区分,这里样式也是照抄掘金
这里我们基本就完成静态样式啦,接下来就是说说怎么触发这个抽奖
抽奖
抽奖的行为是由gridPrize的startRoll函数提供的,这里通过ref获取gridRoll的实例,定义一个handleLottery方法用来触发startRoll函数。再把handleLottery绑定的抽奖按钮上
methods: {
async handleLottery() {
const value = 1;
/**
* 这里的value为1是指抽取id为1的奖品
* 返回一个Promise实例,内部为了防止多次触发抽奖逻辑,
* resolve会传递一个Boolean,进行是false,抽奖结束返回true
*/
const b = await this.$refs.dial.startRoll(value);
if (b) {
alert(
`🎉你抽到${this.prizes.find((prize) => prize.id === value).text}`
);
} else {
console.warn("稍安勿躁");
}
},
},
同时别忘记了,抽奖滚动的时候,有一个选中的样式,这里gridPrize作用域插槽提供了一个isSelect值用来判断是否滚动到当前奖品,用来做一些样式切换