Vue 计算属性已更新,但组件未重新渲染

Posted

技术标签:

【中文标题】Vue 计算属性已更新,但组件未重新渲染【英文标题】:Vue computed property updated, but component did not re-render 【发布时间】:2020-12-16 02:46:57 【问题描述】:

我正在用异步加载到 vuex 存储中的数据填充 vuetify 数据表。 用户输入可以更改存储,在这种情况下,我 dispatch 一个动作,异步拉取一些数据,commits 更改。

为了在数据加载时处理组件状态,我在商店中使用了loading 标志。加载数据时,设置为loading,这样数据表就会呈现为空

...
computed: 
  ... // a fairly long list of interdependent computed properties
  loading() 
    return store.state.loading
  ,
  dataToDisplay() 
     if(this.loading)
        return []
      else
        return store.state.data
     
  

这很好用,但有时数据表组件不会更新,即使提供它的计算属性已更新(参见 vue 开发工具的屏幕截图)。

关于为什么计算属性不更新有几个答案(here、here)。但是有什么可以解释计算的属性确实更新正确,但组件没有重新渲染?如何解决?

有人提到here 使用:key 我试过了,但表格内容仍然没有更新。

[编辑] 提供数据表代码

<v-data-table 
   :key="loading"
   :headers="headers"
   :items="dataToDisplay"
   :item-key="itemId"
   disable-pagination hide-default-footer
>
  <template v-slot:item="row">
  <tr>
    <td class="text-xs-right"> row.item.currentCondition </td>
    <td class="text-xs-right"> row.item.nextCondition </td>
    <td class="mx-2">
      <v-btn icon class="mx-0" @click="editItem(row.item)">
        <v-icon color="teal">mdi-pencil</v-icon>
      </v-btn>
      <v-btn icon class="mx-0" @click="deleteItem(row.item)">
        <v-icon color="pink">mdi-delete</v-icon>
      </v-btn>
    </td>
  </tr>
  </template>
</v-data-table>

【问题讨论】:

从这篇文章中,我可以强制重新渲染。话虽如此,我最好知道发生了什么以提出更好的解决方案michaelnthiessen.com/force-re-render 如果您的key 更新,您的组件将自动重新渲染。否则你需要强制重新渲染。 好的,那么数据表的键是什么?你说的是item-key吗?为了提供更多上下文,我将 [col1:value, col2:value, col1:value,col2:value] 传递给&lt;v-data-table :items="dataToDisplay" :item-key="idNumber"&gt; 这很好用,但有时数据表组件不更新你什么时候有这种行为?请分享商店代码 存储相当复杂,但本质上流程是:用户删除或过滤掉一个表格元素。这会向 firebase 提交请求,并同时从商店中删除该元素。 【参考方案1】:

您可以使用数据属性 items: null 由您的函数填充并使用 v-for: (item, i) in items 将它们加载到您的 v-data-table

<template>
  <v-data-table
    :headers="headers"
    :items="items"
    :loading="loading"
  ></v-data-table>
</template>

<script>
  export default 
    data () 
      return 
        headers: [
           text: 'Name', align: 'start', value: 'name',
           text: 'Description', value: 'desc' ,
        ],
        items: null,
        loading: true
      
    ,
    created: 
      addData() 
        this.items = store.state.data
        this.loading = store.state.loading
      
    
  
</script>

【讨论】:

太好了,谢谢!不过,用户确实会不时修改状态。这意味着在那之后需要重新加载状态。所以我猜 created() 钩子可以用于初始化,但不能用于初始化。 Vuetify 使数据表在v-for 中使用的项目发生变化时更新。你可以使用计算,但我强烈建议也使用数据属性。 我没有使用 v-for (抱歉问题含糊不清,我更新了模板)。在您的解决方案中,用户操作后更新项目的逻辑在哪里?那么它们会在方法内部,而不是通过计算字段触发吗?

以上是关于Vue 计算属性已更新,但组件未重新渲染的主要内容,如果未能解决你的问题,请参考以下文章

VueJS 计算属性未在 DOM 上更新

vue 计算属性未重新计算 / computed 未触发 / computed 原理&源码分析

vue 计算属性未重新计算 / computed 未触发 / computed 原理&源码分析

Vue的计算属性

组件渲染时Vue JS计算属性尚不可用

Vue面试题集锦