在循环完成之前,VueJS不会重新渲染

时间:2019-04-13 14:19:44

标签: javascript vue.js vuejs2

我有这段VueJS代码:

new Vue({
  el: '#app',
  data: {
    tiles: [
      { isActive: false },
      { isActive: false },
      { isActive: false },
      { isActive: false },
      { isActive: false }
    ]

  },
  methods: {
    startWithLoop: function() {
      console.log("startWithLoop");
      for(var i = 0; i < 10000; i++ ) { this.blink() };
    },
    startWithInterval: function() {
      console.log("startWithInteral");
      setInterval(this.blink);
    },
    blink: function(){
      console.log("blink");
      var index = Math.floor(Math.random() * this.tiles.length);
      this.tiles[index].isActive = !this.tiles[index].isActive;
    }
  }
})

如果我调用方法startWithInterval,则在视图中可以看到tiles一直在改变状态。

如果我调用方法startWithLoop,直到循环完成,我看不到视图的任何变化。

这里是the JSFiddle

如何在循环的每个步骤中触发视图更改?

3 个答案:

答案 0 :(得分:2)

不,这是Javascript eventloop在浏览器中的工作方式(不仅如此)。

您可以想象Javascript只在“瞬间之间的间隔”中执行,因此您对浏览器中发生的情况的了解只是瞬间的快照。

答案 1 :(得分:0)

您可以编写类似setTimeout的类似循环的内容,以使Vue注意到更改,然后将其推送到DOM。

beforeDestroy() {
  if (this.timeout != null) {
    clearTimeout(this.timeout);
    this.timeout = null;
  }
},
startWithLoop: function() {
  console.log("startWithLoop");
  let i = 0
  const iter = () => {
    this.blink();
    i += 1;
    if (i < 10000) {
      this.timeout = setTimeout(iter);
    }
  }
  iter();
},

研究上面的更改:https://jsfiddle.net/ssorallen/9pqscat1/3/

答案 2 :(得分:0)

总结并结合所有建议,我了解到:

  • 在JS循环中间,VueJS不会重新渲染任何东西

因此,您必须将循环的迭代移至另一个进程。我当时以为 promises 是一种解决方案,但是更简单的方法是使用setTimeout()而不使用 delay 参数。

所以代替这个:

for(var i = 0; i < 10000; i++ ) { 
  this.blink() 
};

我的代码如下:

for(var i = 0; i < 10000; i++ ) { 
  setTimeout(this.blink)
}