原文链接: 面向对象与vue的结合
上一篇: vue 重新挂载 解决数据刷新问题
下一篇: Ubuntu vscode 安装和卸载
将操作和实现分离
把函数式改为面向对象的形式
在视图层 只调用对象的方法
然后重新挂载,达到刷新视图的效果
但是重新挂载会导致自动求解时没有过渡动画。。。。。
Maze
class Maze {
constructor(size) {
this.size = size
this.blank = size * size
this.items = Array.from(Array(size * size)).map((_, index) => index + 1)
this.initCnt = 1000
}
// 是否完成
isPass() {
return this.items.every((item, index) => item == index + 1)
}
// 空白块所在位置0....1....
blankPos() {
return this.items.indexOf(this.blank)
}
// 移动
move(dir) {
// console.log(dir)
if (dir == 0 && this.blankPos() >= this.size) {
this.swap(this.blankPos(), this.blankPos() - this.size)
} else if (dir == 1 && this.blankPos() % this.size != (this.size - 1)) {
this.swap(this.blankPos(), this.blankPos() + 1)
} else if (dir == 2 && this.blankPos() < (this.size - 1) * this.size) {
this.swap(this.blankPos(), this.blankPos() + this.size)
} else if (dir == 3 && this.blankPos() % this.size != 0) {
this.swap(this.blankPos(), this.blankPos() - 1)
}
}
// 交换
swap(x, y) {
// console.log(x, y)
let t = this.items[x]
this.items[x] = this.items[y]
this.items[y] = t
}
shuffle() {
for (let i = 0; i < this.initCnt; i++)
this.move(
Math.floor(Math.random() * 1000) % 4
)
}
toString() {
return this.items.toString()
}
}
Game
<template>
<div class="main">
<select v-model="size">
<option value="3"> 3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
<p>选择:{{size}}</p>
<transition-group name="cells" tag="div" class="game" ref="game">
<div v-for="i,index in maze.items" class="cell"
:key="i"
@click="click(i,index)"
>
{{i==size*size?'':i}}
</div>
</transition-group>
<button @click="shuffle">reset</button>
<button @click="autoplay">autoplay</button>
</div>
</template>
<script>
import Maze from './Maze'
export default {
name: "game",
data() {
return {
size: 4,
maze: null
}
},
computed: {
blank() {
}
},
watch: {
size: {
handler: 'init',
},
},
methods: {
init() {
console.log('init')
this.maze = new Maze(this.size)
this.$refs.game.$el.style.width = this.size * 80 + 'px'
this.$refs.game.$el.style.height = this.size * 80 + 'px'
this.$refs.game.$el.style.gridTemplateColumns = `repeat(${this.size},1fr)`
},
shuffle() {
this.maze.shuffle()
this.$mount()
},
autoplay() {
},
click(item, index) {
console.log('click', item, index)
if (item == 16)
return
if (index + 1 < 16 && this.maze.items[index + 1] == 16) {
// console.log('click move', 3)
this.maze.move(3)
} else if (index - 1 >= 0 && this.maze.items[index - 1] == 16) {
this.maze.move(1)
// console.log('click move', 1)
} else if (index + 4 < 16 && this.maze.items[index + 4] == 16) {
this.maze.move(0)
// console.log('click move', 0)
} else if (index - 4 >= 0 && this.maze.items[index - 4] == 16) {
this.maze.move(2)
// console.log('click move', 2)
}
// this.maze.shuffle()
this.$mount()
// console.log(this.$mount())
}
},
created() {
this.maze = new Maze(this.size)
},
mounted() {
console.log('mounted', this.$refs)
this.init()
}
}
</script>
<style scoped>
.main {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
}
.game {
display: grid;
grid-gap: 5px;
background: rgb(233, 233, 233);
border: 5px solid rgb(233, 233, 233);
grid-template-columns: repeat(4, 1fr);
}
.cell {
display: flex;
width: 100%;
height: 100%;
background: lightskyblue;
justify-content: center;
align-items: center;
}
.cells-enter-active, .cells-leave-active {
transition: all 0.5s;
}
/*效果*/
.cells-enter, .cells-leave-to {
opacity: 0;
transform: translateY(30px);
}
/*过渡时间*/
.cells-move {
transition: transform 0.5s;
}
</style>