需求
将一份名单渲染到页面上,页面中有一个按钮,点击按钮随机从名单中抽取一个人,要有动态效果。
实现
完整代码
<template>
<div>
<div class="name-list">
<div
class="name"
:class="index === selectedIndex ? 'selected' : ''"
v-for="(name, index) in list"
:key="index"
>
{{ name }}
</div>
</div>
<div class="select-btn">
<button @click="startSelect">点击进行抽取</button>
</div>
</div>
</template>
<script>
export default {
props: {
list: {
type: Array,
required: true,
},
},
data() {
return {
selectedIndex: 0, //被抽中的人在数组中的下标
timeID: "", //当前定时器的ID
};
},
methods: {
//开始抽取
startSelect() {
//要使用节流阀
if (this.timeID) return; //保持只有一个定时器在运作
//定时器
// this.selectedIndex = 0; //从第一个人开始抽取
const MIN = this.list.length; //生成随机数的左区间
const MAX = this.list.length * 3; //生成随机数的右区间
let end = Math.floor(MIN + Math.random() * (MAX - MIN)); //终止抽取
console.log(end);
let count = 0; //计数器
this.timeID = setInterval(() => {
//先判断,再执行
if (end === count) {
clearInterval(this.timeID); //清除定时器
this.timeID = ""; //置空,不然只能抽取一次
}
if (this.selectedIndex === this.list.length - 1) {
this.selectedIndex = 0; //置零,不然下标溢出了
} else {
//置零和自加是互斥的,不然的话刚置零又被自加成1了
this.selectedIndex++;
}
count++;
}, 100);
},
},
};
</script>
<style scoped>
.name-list {
width: 600px;
/* height: 300px; */
margin: 0 auto;
/* border: 1px black solid; */
display: flex;
/* 项目排列方向 默认row 左到右*/
flex-direction: row;
/* 项目换行 默认nowrap不换行 wrap第一行在上*/
flex-wrap: wrap;
/* 项目在主轴的对齐方式 水平分隔*/
justify-content: space-between;
/* 项目在交叉轴的对齐方式 垂直居中*/
align-items: center;
/* 多根轴线的对齐方式 */
align-content: flex-start;
}
.name {
min-width: 10%;
margin: 1px;
padding: 5px;
border: 1px solid black;
text-align: center;
}
.selected {
background-color: rgb(30, 216, 230);
font-weight: bold;
}
.select-btn {
text-align: center;
margin-top: 30px;
}
</style>
代码分析
props: {
list: {
type: Array,
required: true,
},
},
组件的属性,list是一个数组,接收父组件传进来的名单,然后渲染在页面上。
本来打算给组件多添加几个属性的,比如控制方向的direction,控制抽取结果的result,控制光圈移动次数的movetimes等等,后面再加吧。
//开始抽取
startSelect() {
//要使用节流阀
if (this.timeID) return; //保持只有一个定时器在运作
//定时器
// this.selectedIndex = 0; //从第一个人开始抽取
const MIN = this.list.length; //生成随机数的左区间
const MAX = this.list.length * 3; //生成随机数的右区间
let end = Math.floor(MIN + Math.random() * (MAX - MIN)); //终止抽取
console.log(end);
let count = 0; //计数器
this.timeID = setInterval(() => {
//先判断,再执行
if (end === count) {
clearInterval(this.timeID); //清除定时器
this.timeID = ""; //置空,不然只能抽取一次
}
if (this.selectedIndex === this.list.length - 1) {
this.selectedIndex = 0; //置零,不然下标溢出了
} else {
//置零和自加是互斥的,不然的话刚置零又被自加成1了
this.selectedIndex++;
}
count++;
}, 100);
},
一开始先判断timeID的值是否为空,不为空说明已经有一个定时器在运作了,直接退出方法。
然后是一些配置参数吧,比如通过随机生成end,来控制光标移动多少次后停下来。count是计数器,从0开始自加,当count等于end的时候就停止抽取了。
selectedIndex则是当前被抽取到的名字在数组中的下标,通过控制它的初始值和自增还是自减可以实现控制光标移动的方向。