// 因为 JavaScript 的限制,Vue.js 不能检测到下面数组变化: // 1.直接用索引设置元素,如 vm.items[0] = {}; // 2.修改数据的长度,如 vm.items.length = 0。 // 为了解决问题 (1),Vue.js 扩展了观察数组,为它添加了一个 $set() 方法: // 与 `example1.items[0] = ...` 相同,但是能触发视图更新 example1.items.$set(0, { childMsg: 'Changed!'})
检测是否闯关成功
<template> <div> <ul> <li :class="{'puzzle': true, 'puzzle-empty': !puzzle}" v-for="puzzle in puzzles" v-text="puzzle" @click="moveFn($index)" ></li> </ul> </div> </template> <script> export default { data () { return { puzzles: [] } }, methods: { // 重置渲染 render () { let puzzleArr = [], i = 1 // 生成包含1 ~ 15数字的数组 for (i; i < 16; i++) { puzzleArr.push(i) } // 随机打乱数组 puzzleArr = puzzleArr.sort(() => { return Math.random() - 0.5 }); // 页面显示 this.puzzles = puzzleArr this.puzzles.push('') }, // 点击方块 moveFn (index) { // 获取点击位置及其上下左右的值 let curNum = this.puzzles[index], leftNum = this.puzzles[index - 1], rightNum = this.puzzles[index + 1], topNum = this.puzzles[index - 4], bottomNum = this.puzzles[index + 4] // 和为空的位置交换数值 if (leftNum === '') { this.puzzles.$set(index - 1, curNum) this.puzzles.$set(index, '') } else if (rightNum === '') { this.puzzles.$set(index + 1, curNum) this.puzzles.$set(index, '') } else if (topNum === '') { this.puzzles.$set(index - 4, curNum) this.puzzles.$set(index, '') } else if (bottomNum === '') { this.puzzles.$set(index + 4, curNum) this.puzzles.$set(index, '') } this.passFn() }, // 校验是否过关 passFn () { if (this.puzzles[15] === '') { const newPuzzles = this.puzzles.slice(0, 15) const isPass = newPuzzles.every((e, i) => e === i + 1) if (isPass) { alert ('恭喜,闯关成功!') } } } }, ready () { this.render() } } </script>
我们在moveFn方法里调用了passFn方法来进行检测,而passFn方法里又涉及了两个知识点:
(1)slice方法
通过slice方法我们截取数组的前15个元素生成一个新的数组,当然前提了数组随后一个元素为空
(2)every方法
通过every方法我们来循环截取后数组的每一个元素是否等于其index+1值,如果全部等于则返回true,只要有一个不等于则返回false
如果闯关成功那么isPass的值为true,就会alert "恭喜,闯关成功!"提示窗,如果没有则不提示。
重置游戏
重置游戏其实很简单,只需添加重置按钮并在其上调用render方法就行了:
<template> <div> <ul> <li :class="{'puzzle': true, 'puzzle-empty': !puzzle}" v-for="puzzle in puzzles" v-text="puzzle" @click="moveFn($index)" ></li> </ul> <button @click="render">重置游戏</button> </div> </template> <script> export default { data () { return { puzzles: [] } }, methods: { // 重置渲染 render () { let puzzleArr = [], i = 1 // 生成包含1 ~ 15数字的数组 for (i; i < 16; i++) { puzzleArr.push(i) } // 随机打乱数组 puzzleArr = puzzleArr.sort(() => { return Math.random() - 0.5 }); // 页面显示 this.puzzles = puzzleArr this.puzzles.push('') }, // 点击方块 moveFn (index) { // 获取点击位置及其上下左右的值 let curNum = this.puzzles[index], leftNum = this.puzzles[index - 1], rightNum = this.puzzles[index + 1], topNum = this.puzzles[index - 4], bottomNum = this.puzzles[index + 4] // 和为空的位置交换数值 if (leftNum === '') { this.puzzles.$set(index - 1, curNum) this.puzzles.$set(index, '') } else if (rightNum === '') { this.puzzles.$set(index + 1, curNum) this.puzzles.$set(index, '') } else if (topNum === '') { this.puzzles.$set(index - 4, curNum) this.puzzles.$set(index, '') } else if (bottomNum === '') { this.puzzles.$set(index + 4, curNum) this.puzzles.$set(index, '') } this.passFn() }, // 校验是否过关 passFn () { if (this.puzzles[15] === '') { const newPuzzles = this.puzzles.slice(0, 15) const isPass = newPuzzles.every((e, i) => e === i + 1) if (isPass) { alert ('恭喜,闯关成功!') } } } }, ready () { this.render() } } </script> <style> @import url('./assets/css/bootstrap.min.css'); body { font-family: Arial, "Microsoft YaHei"; } .box { width: 400px; margin: 50px auto 0; } .puzzle-wrap { width: 400px; height: 400px; margin-bottom: 40px; padding: 0; background: #ccc; list-style: none; } .puzzle { float: left; width: 100px; height: 100px; font-size: 20px; background: #f90; text-align: center; line-height: 100px; border: 1px solid #ccc; box-shadow: 1px 1px 4px; text-shadow: 1px 1px 1px #B9B4B4; cursor: pointer; } .puzzle-empty { background: #ccc; box-shadow: inset 2px 2px 18px; } .btn-reset { box-shadow: inset 2px 2px 18px; } </style>
这里我一并加上了css代码。
总结