Vue v-for性能差

时间:2017-05-11 10:58:22

标签: javascript performance vue.js

我通过AJAX返回了大约4000个对象。我用v-for循环它们并将它们吐出到表中。

初始加载和渲染非常快,但我也有一个输入字段,用于即时搜索'。我使用一个计算属性来使用输入值和一个小数据集来过滤数据集,比如最多大约100个结果,这可以很好地工作,但随着数据集变大,它会慢得多。

我正在渲染一个包含4个值的表,其中一个是自定义组件。删除组件会加快速度,但我很惊讶它的性能受到了很大影响。我不确定是否有我失踪的东西,或者有人能指出我正确的方向吗?

我知道一页的大量数据,但我认为这是Vue应该擅长的。我搜索了这个问题,例如我发现这个codepen呈现了一个类似的项目列表,并以完全相同的方式进行过滤,我可以将数组中的项目数量一直复制粘贴到10,000左右,并且搜索时没有明显的性能损失。

我已经采取了加快步伐的步骤,这些步骤已经做了很小的改进或没有改进:

  • 在v-for
  • 上添加了一个v-bind:key,其唯一值
  • 不使用table元素而是使用div或ul
  • 放弃nativeJS .filter方法,因为它可能很慢,并且使用我自己的过滤器 方法。
  • 尝试在仅包含依赖项的新代码库上运行它 需要运行。
  • 我知道分页技术等,但我不愿意 除非我已经用尽所有其他可能性,否则就这样做。

由于

它希望我在这里粘贴代码,即使我已经链接到codepen,所以这里的JS没有items数组。

    Vue.component('my-component', {
  template: '#generic-picker',
  props:['items','query','selected'],
  created: function(){
    this.query='';
    this.selected='';
  },
  computed:{
    filteredItems: function () {
      var query = this.query;
      return this.items.filter(function (item) {
        return item.toLowerCase().indexOf(query.toLowerCase()) !== -1})
    }
  },
  methods:{
    select:function(selection){
      this.selected = selection;
    }
  }
})
// create a root instance
var genericpicker = new Vue({
  el: '#example'
});

2 个答案:

答案 0 :(得分:6)

使用计算数组的问题在于,当您处于v-if的情况时,事物必须取消渲染并重新渲染,就好像您正在使用v-show一样更好的选择。

相反,请为每个项目保留一个指示符,以确定是否应显示该项目,并根据该项目使用v-show。下面的代码段实现了两个,可通过复选框选择。如果不使用v-show版本,您会发现过滤器更新有点暂停,但在使用v-show时保持良好状态。

当你将其过滤到0行时最明显(比如,在x上过滤)然后显示所有内容(删除过滤器),但你可以看到部分过滤的差异,如me 2

let arr = [];
for (let i=0; i<6000; ++i) {
  arr.push({name: `Name ${i}`, thingy: `Thingy ${i}`});
}

Vue.component('tableRow', {
      template: '<tr><td>{{name}}</td><td>{{thingy}}</td></tr>',
      props: ['name', 'thingy']
    }
);

new Vue({
  el: '#app',
  data: {
    arr,
    filter: 'x',
    useVshow: false
  },
  computed: {
    filteredArr() {
      return this.filter ? this.arr.filter((item) => item.name.indexOf(this.filter) > -1) : this.arr;
    }
  },
  watch: {
    filter() {
      for (const i of this.arr) {
        i.show = this.filter ? i.name.indexOf(this.filter) > -1 : true;
      }
    }
  }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.min.js"></script>
<div id="app">
  Filter: <input v-model="filter">
  Use v-show: <input type="checkbox" v-model="useVshow">
  <table>
    <tr>
    <th>Name</th>
    <th>Thingy</th>
    </tr>
    <template v-if="useVshow">
    <tr is="tableRow" v-for="row in arr" v-show="row.show" :key="row.name" :name="row.name" :thingy="row.thingy"></tr>
    </template>
    <template v-else>
    <tr is="tableRow" v-for="row in filteredArr" v-show="row.show" :key="row.name" :name="row.name" :thingy="row.thingy"></tr>
    </template>
  </table>
</div>

答案 1 :(得分:0)

如果您对双向和/或反应性绑定不感兴趣,也就是说,如果您只想可视化对象而不是能够在数据更改时编辑它们或更新视图,则可以加快速度Object.freeze可以显着提高性能。这样,Vue.js不能在每个属性上添加观察者,而只能读取属性。