Vue v-for性能很差

peo*_*eos 5 javascript performance vue.js

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

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

我正在渲染一个包含4个值的表,其中一个是自定义组件.删除组件可以加快速度,但我很惊讶这是一个糟糕的性能影响.我不确定是否有什么东西我不知道或者有人能指出我正确的方向吗?

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

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

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

谢谢

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

    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'
});
Run Code Online (Sandbox Code Playgroud)

Roy*_*y J 8

使用计算数组的问题在于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;
      }
    }
  }
});
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


wen*_*een 6

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