使用内置过滤器的Vue.js b-table子组件:工作正常但非常缓慢

使用内置过滤器的Vue.js b-table子组件:工作正常但非常缓慢,vue.js,filtering,bootstrap-vue,Vue.js,Filtering,Bootstrap Vue,我有一个vue页面Main.vue,它从单独的vue文件Table.vue呈现组件。当我将所有逻辑都烘焙到Main.vue中时,自由格式文本过滤器工作正常。但现在我输入的几乎每个字符都会延迟,所以我想我的实现可能有问题 我在下面发布的代码经过了简化,即删除了分页和计算内容,以显示我所坚持的内容 表3.vue: Main.vue: <template> <div v-if="details !== null"> <custtable :detail

我有一个vue页面Main.vue,它从单独的vue文件Table.vue呈现组件。当我将所有逻辑都烘焙到Main.vue中时,自由格式文本过滤器工作正常。但现在我输入的几乎每个字符都会延迟,所以我想我的实现可能有问题

我在下面发布的代码经过了简化,即删除了分页和计算内容,以显示我所坚持的内容

表3.vue:

Main.vue:

<template>
  <div v-if="details !== null">
      <custtable :details="filteredDetails"/>
      <br/>
  </div>
</template>

<script>

import { API } from '@/common/api.js'
import Table from '@/components/Table'

export default {
    name: 'Main',
    data: function() {
        return {
            details: [],
            filteredDetails: []
        }
    },
    components: {
        'custtable': Table
    }
}

</script>
所以我想知道过滤器部分是否应该在表中。vue:它应该在Main.vue中吗?理想情况下,应该在哪里定义过滤器变量

如前所述,功能是存在的,但它似乎非常缓慢。最初的API调用通常会返回大约150个JSON条目,因此数据量不会太大

到目前为止,我一直在引用


任何和所有的输入是感激的

如果您的表具有唯一的ID字段,即主键,请通过主键属性指定该字段键名称。这将优化Vue重新呈现表的方式

i、 e.如果您的items数组有一个字段id,该id保证在所有数据行中都是唯一的,则设置prop primary=key=id

过滤还需要将每一行的数据序列化为包含所有行值的单个字符串,因此如果有许多字段或深嵌套字段,则可能需要一些时间

另一个选项是消除过滤器输入的干扰。与其将过滤器输入的v模型直接传递给b-table的过滤器属性,不如将其存储在一个中间变量中,并且只在如此多毫秒的无按键输入事件后更新发送给b-table的输入值的副本


在您的情况下,筛选器进程会在输入的每个字符的整个表中运行,这会重新触发Vue以重新呈现整个表。结合使用主键和输入去抖动应该可以提高性能

感谢特洛伊提供的信息丰富的回答。我确实设置了主键,这对渲染略有帮助,但仍然非常缓慢。看看下面的Vue检查器,它不应该列出实际的PK值而不是票证号吗?请参见此处:主键属性需要字段名,而不是字段值。它使用该名称从items行中查找值,并根据查找到的值为该行指定Vue:键。因此,每个都会分配一个唯一的Vue:key,因此如果行数据没有更改,Vue可以优化其渲染。它还可以重新排列DOM元素,即在排序或过滤已经呈现的元素时,只要vNode键没有改变。啊,这很有帮助!当我现在只使用常规的Inspect元素功能时,我可以看到每个元素都有一个带有票证号的数据pk属性。令人惊叹的如果您检查VM中的TR元素及其vNode引用,您还将看到根据行主键值分配了唯一的Vue键。只是想签入并查看用于在表单输入上取消公告的PR,它的工作方式很有魅力。谢谢你所做的一切!
<script>

export default {
  name: 'Table',
  props: ['details'],
  data: function() {
    return {
      fields: [
        { key: 'ticket_number', sortable: true },
        { key: 'parent_id', label: 'Parent Ticket', sortable: true },
        { key: 'start', sortable: true, label: 'Start Date', formatter: (value) => { return moment(value, 'X').format('MM/DD/YYYY hh:mm:ss A') }},
  ],
  // free text filter
  filter: null
  }
},
  computed: {
  rows: function(){
    return this.details.length
  }
},
created: function () {
  this.filteredDetails = this.details
},
methods: {
  onFiltered(filteredItems) {
    // Trigger pagination to update the number of buttons/pages due to filtering
    this.totalRows = filteredItems.length
    this.currentPage = 1
    }
  }
}
<template>
  <div v-if="details !== null">
      <custtable :details="filteredDetails"/>
      <br/>
  </div>
</template>

<script>

import { API } from '@/common/api.js'
import Table from '@/components/Table'

export default {
    name: 'Main',
    data: function() {
        return {
            details: [],
            filteredDetails: []
        }
    },
    components: {
        'custtable': Table
    }
}

</script>