题目
分析
可以从题目中拆分两个组件:
- 信号灯
- 控制器
信号灯需要做的事情:
- 接收配置信息。
- 亮、闪烁。
- 结束后通知控制器。
控制器需要做的事情:
- 接收配置信息,根据配置信息创建信号灯。
- 信号灯编排:接受信号灯的结束通知,并启动下一个信号灯。
难点:
- 信号灯的亮、闪烁。
- 信号灯结束,控制器启动下一个信号灯。
这里等待操作,显然需要通过异步来实现,我们可以先去复习Promise和async函数。
控制台版
function Light(color, duration, twinkleDuration) { // 信号灯
let brightDuration = duration - twinkleDuration;
function bright() { // 亮
return new Promise(function (resolve, reject) {
console.log(`${color}灯开始亮`)
setTimeout(resolve, brightDuration);
})
}
function twinkle() { // 闪烁
return new Promise(function (resolve, reject) {
console.log(`${color}灯开始闪烁`)
setTimeout(resolve, twinkleDuration);
})
}
function start() { // 启动信号灯
return new Promise(async function (resolve, reject) {
await bright() // ①
await twinkle() // ②
console.log(`${color}灯灭掉`)
resolve()
})
}
return {
start
}
}
function timer() { // 计时器,用来测试
let start = new Date()
let now = new Date()
function next() {
now = new Date()
console.log(`第${Math.floor((now - start) / 1000)}秒`)
setTimeout(next, 1000)
}
next()
}
async function LightControl(lightOptions) { // 信号灯控制器
for (let { color, duration, twinkleDuration } of lightOptions) {
await Light(color, duration, twinkleDuration).start() // ③
}
}
timer()
LightControl([
{ color: "红", duration: 4000, twinkleDuration: 2000, },
{ color: "绿", duration: 5000, twinkleDuration: 3000, },
{ color: "黄", duration: 6000, twinkleDuration: 4000, },
])
!!! 在①②③处,存在层次的回调,我们使用async函数来简化代码。
输出结果:
第0秒
红灯开始亮
第1秒
红灯开始闪烁
第2秒
第3秒
红灯灭掉
绿灯开始亮
第4秒
第5秒
绿灯开始闪烁
第6秒
第7秒
第8秒
绿灯灭掉
黄灯开始亮
第9秒
第10秒
黄灯开始闪烁
第11秒
第12秒
第13秒
第14秒
黄灯灭掉
第15秒
第16秒
输出符合预期,信号灯依次闪烁。
Vue版
下面,我们把代码稍微进行一下修改,让该信号灯显示在网页中。
// @/components/LightControl.vue
<template>
<div>
<Light v-for="(lightOption,index) of lightOptions"
:lightOption="lightOption"
:status="lightStatus[index]"
:key="index"
/>
<div>计时器:{{ time }}</div>
<div>option: {{lightOptions}}</div>
</div>
</template>
<script>
import Light from '@/components/Light'
export default {
name: "LightControl",
data: function () {
return {
lightOptions: [
{color: "#FF0000", duration: 6000, twinkleDuration: 2000,},
{color: "#00FF00", duration: 5000, twinkleDuration: 3000,},
{color: "#FFFF00", duration: 6000},
],
lightStatus: [0, 0, 0],
time: 0,
}
},
components: {
Light
},
created() {
this.lightControl(this.lightOptions)
this.startTimer()
},
methods: {
startTimer() {
let start = new Date()
let now = new Date()
let that = this
function next() {
now = new Date()
that.time = Math.floor((now - start) / 1000)
setTimeout(next, 1000)
}
next()
},
changeStatus: function (i, value) {
this.lightStatus.splice(i, 1, value)
},
createLight: function (color, duration, twinkleDuration=0, i) { // 信号灯
let brightDuration = duration - twinkleDuration
let that = this
function bright() { // 亮
return new Promise(function (resolve) {
that.changeStatus(i, 1)
setTimeout(resolve, brightDuration);
})
}
function twinkle() { // 闪烁
return new Promise(function (resolve) {
that.changeStatus(i, 2)
setTimeout(resolve, twinkleDuration);
})
}
function start() { // 启动信号灯
return async function () {
await bright()
await twinkle()
that.changeStatus(i, 0)
}()
}
return {
start
}
},
lightControl: async function (lightOptions) {
for (let i = 0; i < lightOptions.length; i++) {
let {color, duration, twinkleDuration} = lightOptions[i]
await this.createLight(color, duration, twinkleDuration, i).start()
}
}
},
}
</script>
<style scoped>
</style>
// @/components/Light.vue
<template>
<div :style="color" :class="lightClass">
</div>
</template>
<script>
export default {
name: "Light",
props: {
lightOption: {
type: Object,
value: null,
},
status: {
type: Number,
value: 0,
},
},
computed: {
lightClass: function () { // 传入的 props => 类名 => 样式
let subClass = 'close'
console.log(this.status)
if (this.status === 1) {
subClass = 'on'
} else if (this.status === 2) {
subClass = 'fade'
}
return ['light', subClass]
}
},
data: function () {
return {
color: "#FFFF00",
}
},
created() {
this.color = {
background: this.lightOption.color
}
},
}
</script>
<style scoped>
.light {
display: inline-block;
height: 30px;
width: 30px;
border-radius: 30px;
}
.on {
opacity: 1;
}
.close {
opacity: 0.2;
}
@keyframes fade {
from {
opacity: 1.0;
}
50% {
opacity: 0;
}
to {
opacity: 1.0;
}
}
.fade {
animation: fade 618ms infinite;
}
</style>
上述代码创建了两个Vue组件Light、LightControl,Light只是负责显示,控制逻辑都写在LightControl里。
效果如下图:
总结
使用JavaScript提供的Promise和async函数,我们可以非常方便等待异步函数。
源码:https://gitee.com/litangmm/myblinker
创作不易!如果对你有帮助,还请点赞收藏。 如果有疑惑可以在下方留言。 如果有什么建议,可以私信我。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!