修改不相关的数据时,Vue.JS 2.0变慢

时间:2016-12-08 15:08:50

标签: javascript vue.js

假设我在Vue.JS中有一个输入字段v-model绑定到一个String数据属性,以及一个与该第一个字符串完全无关的随机数列表。

data: {
  input: "",
  randoms: []
}

<input type="text" v-model="input">
<p v-for="random in randoms" v-text="random"></p>

当我把两者放在同一个Vue中时,我在输入字段中输入时看到一个巨大的减速,因为看起来Vue在每个输入事件后重新评估每个列表条目的DOM,尽管它们实际上与每个输入事件无关。其他

https://jsfiddle.net/5jf3fmb8/2/

然而,当我将v-for移动到我将randoms绑定到道具的子组件时,我没有遇到这样的减速

https://jsfiddle.net/j601cja8/1/

有没有一种方法可以在不使用子组件的情况下实现第二小提琴的表现?

2 个答案:

答案 0 :(得分:7)

  

有没有一种方法可以在不使用子组件的情况下实现第二小提琴的表现?

简短回答

没有

答案很长

每当模板的任何依赖关系发生变化时,Vue必须重新运行整个组件的渲染功能,并将新的virtualDOM与新的虚拟目标区分开来。它不能仅为 部分模板执行此操作,并跳过其余部分。因此,每次inpot值改变时,都会重新渲染整个virutalDOM。

由于你的v-for产生了相当多的元素,这可能需要几百毫秒,足以在你输入时显而易见。

将模板的重要部分提取到自己的组件中实际上是&#34;官方&#34;优化它的方法。

正如亚历克斯解释的那样,v-model.lazy可能会改善这种情况,但不会解决问题的核心。

答案 1 :(得分:1)

最短,最简单的答案:将v-model更改为v-model.lazy

  

当我把两者放在同一个Vue中时,我在输入字段中输入时看到一个巨大的减速,因为看起来Vue在每个输入事件后重新评估每个列表条目的DOM,尽管它们实际上与每个输入事件无关。其他

请注意,OnceFor样本仍然突然疯狂,尽管实际上不再是被动反应。我不太了解Vue是否有意或无意。

const Example = {
  data() { return { input: "", randoms: [] } },
  created() { this.newRandoms() },
  methods: {
    newRandoms() { this.randoms = Array(50000).fill().map(() => Math.random()) }
  }
}

new Vue({
  el: "#vue-root",
  data(){ return {example: 'lazy-model'}},
  components: {
    LazyModel: {...Example, template: "#lazy-model"
    },
    OnceFor: {...Example, template: "#once-for"
    },
    InlineTemplate: {...Example, template: "#inline-template",
        components: {
          Welp: {
            props: ['randoms']
          }
        }
    }
  }
})
button,
input,
div {
  margin: 2px;
}
<script src="https://unpkg.com/vue/dist/vue.js"></script>

<div id="vue-root">
  <span><button v-for="(component, name) in $options.components" @click="$set($data, 'example', name)">{{name}}</button></span>
  <component :is="example"></component>
</div>

<template id="lazy-model">
<div>
  <input type="text" v-model.lazy="input"><br>
  <input type="submit" value="Regenerate" @click="newRandoms">
  <p v-for="random of randoms" v-text="random"></p>
</div>
</template>

<template id="once-for">
<div>
  <input type="text" v-model="input"><br>
  <input type="submit" value="Regenerate" @click="newRandoms">
  <p v-for="random of randoms" v-text="random" v-once></p>
</div>
</template>

<template id="inline-template">
<div>
  <input type="text" v-model="input"><br>
  <input type="submit" value="Regenerate" @click="newRandoms">
  <welp :randoms="randoms" inline-template>
    <div>
      <p v-for="(random, index) of randoms" :key="index"> {{index}}: {{random}} </p>
    </div>
  </welp>
</div>
</template>