简体   繁体   English

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

[英]VueJS doesn't re-render until loop is finished

I have this piece of VueJS code: 我有这段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;
    }
  }
})

If I call the method startWithInterval I can see in the view how the tiles are changing state all the time. 如果我调用该方法startWithInterval我可以在视图如何看tiles正在改变状态的所有时间。

If I call the method startWithLoop I don't see any change in the view until the loop is finished. 如果我调用方法startWithLoop ,则在循环完成之前,视图中看不到任何更改。

Here is the JSFiddle 这是JSFiddle

How can I trigger changes in the view on each step of the loop? 如何在循环的每个步骤中触发视图更改?

No, this is how Javascript eventloop works in browsers (and not only). 不,这是Javascript eventloop在浏览器中的工作方式(不仅如此)。

You can imagine that Javascript only gets executed in "gaps between moments", so that your picture of what happens in the browser is a still snapshot of the moment. 您可以想象Javascript只在“瞬间之间的间隔”中执行,因此您对浏览器中发生的情况的了解只是瞬间的快照。

You could write something loop-like that uses setTimeout to let changes be noticed by Vue and then pushed to the DOM. 您可以编写类似于setTimeout类似于loop的内容,以使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();
},

Working fiddle with the changes from above: https://jsfiddle.net/ssorallen/9pqscat1/3/ 处理上面的更改: https : //jsfiddle.net/ssorallen/9pqscat1/3/

Wrapping up and as a merge of all the suggestions, I have understood that: 总结并结合所有建议,我了解到:

  • In the middle of a JS loop VueJS is not gonna re-render anything 在JS循环中间,VueJS不会重新渲染任何东西

So you have to move the iterations of your loop to another process. 因此,您必须将循环的迭代移至另一个进程。 I was thinking that promises can be a solution but an easier one is to use setTimeout() without the delay param. 我当时以为promise可以解决,但更简单的方法是使用setTimeout()而不使用延迟参数。

So instead of this: 所以代替这个:

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

My code would look like this: 我的代码如下所示:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM