Vue.js 过渡和效果乱序执行

Vue.js Transitions and effects executing out of order

我正在制作井字游戏网络应用程序。它还没有完成,因为这个问题已经抛出了障碍。当 X 或 O 获胜时,它应该将 3 个获胜框变为绿色(如果我删除了我希望在那之后发生的过渡,这部分工作)。一旦框为绿色,整个 'Board' table 应该 'bounce out'。但实际发生的情况是,'Board' 在 'mark' (X/O) 显示之前跳出并且获胜框变为绿色。对我来说没有意义的是,代码执行的重点应该是从上到下,但它的行为似乎并不像那样。我试过用几种不同的方式重新排列代码,但仍然没有成功。

Here is the Codepen

这里是为那些不想点击 link 的人准备的代码 :P(抱歉样式问题,代码片段无法正常工作 =/

顺便说一句,提前致谢!

console.clear();
const log = console.log.bind(console);

const game = new Vue({
 el: '#app',
 data: {
  turn: 'X',
  over: false,
  board: [[{val:'',bg:''}, {val:'',bg:''}, {val:'',bg:''}],
       [{val:'',bg:''}, {val:'',bg:''}, {val:'',bg:''}],
       [{val:'',bg:''}, {val:'',bg:''}, {val:'',bg:''}]],
  windex: [[[0,0], [0,1], [0,2]],
       [[1,0], [1,1], [1,2]],
       [[2,0], [2,1], [2,2]],
       [[0,0], [1,0], [2,0]],
       [[0,1], [1,1], [2,1]],
       [[0,2], [1,2], [2,2]],
       [[0,0], [1,1], [2,2]],
       [[0,2], [1,1], [2,0]]],
  check() {
   const arr = this.board.map( x => x.map( y => y.val ));
   const winArr = this.windex.map( x => x.map( y => this.board[y[0]][y[1]].val ));
   const winner = winArr.map( (x,ind) => {
    if( x.every( y => y == 'X' )) return 'X';
    if( x.every( y => y == 'O' )) return 'O';
   });
   if(winner.includes('X')){
    const inds = this.windex[winner.indexOf('X')];
    inds.forEach( x => {
     this.board[x[0]][x[1]].bg = 'active';
    });
    this.over = true;
   };
   if(winner.includes('O')){
    const inds = this.windex[winner.indexOf('O')];
    inds.forEach( x => {
     this.board[x[0]][x[1]].bg = 'active';
    });
    this.over = true;
   };
   if(arr.every( x => x.every( y => y == 'X' || y == 'O' )))
    this.over = true;
  }
 },
 methods: {
  mark(box) {
   if(this.over) return
   if(box.val === ''){
    box.val = this.turn;
    this.turn = this.turn == 'X' ? 'O' : 'X';
   } else 
     alert('Invalid turn')
    this.check()
  }
 }
});
@import 'https://fonts.googleapis.com/css?family=Oswald';

h1 {
 font-family: 'Oswald';
 letter-spacing: 1.5vw;
 text-align: center;
 margin:1vw;
}

table {
 margin-left: auto;
 margin-right: auto;
 border-collapse: separate;
 border-spacing: 2px;
}

.square {
 width: 100px;
 height: 100px;
 background-color: #6C7A89;
 text-align: center;
 color: white;
 cursor: pointer;
 text-align: center;
 line-height: 100px;
 font-size: 50px;
 font-family: 'Oswald';
 display: block;
}

.square:hover {
 opacity: .8;
}

td {
 vertical-align: middle;
}

.active {
 background-color: #00B16A;
}

.bounce-leave-active {
  animation: bounce-out 1.5s;
}

@keyframes bounce-out {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.5);
  }
  100% {
    transform: scale(0);
  }
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.1/vue.min.js"></script>

<div id='app'>
 <h1>TIC-TAC-TOE</h1>
 <transition name='bounce'>
 <table v-if='!over'>
  <tr v-for='row in board'>
   <td v-for='box in row'>
    <div class='square' 
       v-bind:class='{active:box.bg}' 
       v-on:click='mark(box)'>
     {{box.val}}
    </div>
   </td>
  </tr>
 </table>
 </transition>
</div>

您的代码作为一个块运行; UI 不会在您的设置 activeover 之间重绘,因此就 UI 而言,它们同时有效地发生。 over 触发了 v-if 绑定,所以内容不会被重新绘制,它们只是过渡出来。

Vue 提供 nextTick 让您可以对事物进行排序。与 setTimeout(..., 0) 一样,它将您的命令带出块,但它确保在执行之前发生 DOM 更新周期。