props不变时,VueJS组件会重新渲染

问题描述

我在vuex存储区中有一个带有表[t1,t2]的列表,当更新t1时,我必须更改表数组才能更新t1。

对于每个表,我使用<Table v-for="(item,index) in tables" :key="index" :data="item">,其中它使用Table.vue。在Table.Vue中,我有

 props: {
   data: {
     type: Object,default: null
   }
 },

但是,当t1更改时,它也将强制更新到t2,这是可以理解的,因为存储中的整个“ tables”变量都发生了变异。但是我只希望组件在道具发生实际变化时进行更新,以免t2不必要地更新。我试图研究记忆,我之前在React-projects中使用它来解决这个问题。我真的没有发现任何易于使用的东西,并且搜索“ memoization vuejs”并没有真正让我继续前进。

我如何在vuex存储中进行突变以对表进行突变:

 my_mutation(state,data) {
    let newList = [...state.tables];
    let index = newList.findindex(i => i.tableName === data.tableName);
    if (index !== -1) {
       newList[index] = data.value;
    } 
    Vue.set(state,'currentViews',newList);
}

如您所见,该代码当时仅在state.tables中变异1个元素,但设置整个表变量。这将导致update()函数在组件中触发(注意,不是created(),因为这仅在我获取并填充表变量时才发生)并重新释放组件。

由于在发生突变时未触发created(),因此这告诉我该组件仍然存在并且不需要重新创建。这里的目标不是在道具没有更改时触发update()并防止重新渲染该特定组件。

解决方法

您可能应该添加一些代码,因为您看到的内容似乎很奇怪...

看下面的例子(更新的例子使用Vuex ...只是为了确定)

  • 第一个按钮更改索引1处第一个表的数据。结果 =仅第一个组件重新呈现
  • 第二个按钮完全替换第二个表的数据。 结果 =仅重新提交第二个组件
  • 第三个按钮用一个新数组替换整个tables数组。 结果 =两个组件的重新渲染(符合预期)
  • 好奇者的第四个按钮;)...由现有实例组成的全新tables数组。 结果 =完全不重新渲染
  • 第五个按钮(Q更新后添加)
    • 与上述问题相同的更新方式
    • 结果-仅第二张表退回!与您所说的明显矛盾...
    • 请注意,如果您从一开始就在currentViews中拥有state属性,则无需使用Vue.set-简单的分配就足够了

更新:在updated组件中添加了带有console.log的{​​{1}}钩子,以检查日志是否与表标题中的时间变化相关-已确认

mytable
Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    tables: [
        ['item 1','item 2'],['item 1','item 2']
      ]
  },mutations: {
    mutate1st(state) {
      Vue.set(state.tables[0],state.tables[0][0]+'+1')
    },mutateTables(state) {
      Vue.set(state.tables,1,['item 3','item 4'])
    },replaceTables(state) {
      state.tables = [
        ['item 1','item 2']
      ]
    },newArrayCreatedFromPreviousOnes(state) {
      state.tables = [...state.tables]  // we are creating new array composed from existing instances
    },sameWayAsInQuestion(state) {
      let newList = [...state.tables];
      newList[1] = ['item 5','item 6'];
      Vue.set(state,'tables',newList);
    } 
  }
})

const mytable = Vue.component('mytable',{
  props: ['title','data'],template: `
    <div>
      <div> {{ title }} ({{ now() }}) </div>
      <div v-for="(item,index) in data" :key="index">{{ item }}</div>
      <hr>
    </div>
  `,methods: {
    now() {
      const date = new Date();
      return date.toLocaleTimeString();
    }
  },updated() {
    console.log(`${this.title} updated at ${this.now()}`)
  }
})

const app = new Vue({
  store,components: { mytable },template: `
    <div>
      <button @click="mutate1st">Mutate 1st table data</button>
      <button @click="mutateTables">Mutate tables array</button>
      <button @click="replaceTables">Replace tables array</button>
      <button @click="newArrayCreatedFromPreviousOnes">Just for curiosity...</button>
      <button @click="sameWayAsInQuestion">Same way as in question</button>
      <hr>
      <mytable v-for="(table,index) in $store.state.tables" :key="index" :title="'Table ' + index" :data="table" />
    </div>
  `,methods: {
    ...Vuex.mapMutations(['mutate1st','mutateTables','replaceTables','newArrayCreatedFromPreviousOnes','sameWayAsInQuestion'])  
  }
})

app.$mount("#app")

,

更新:我在Table.vue中还有另一个组件,该组件依赖于存储变量,该存储变量在更改t1时发生了突变,导致其余表发生更改。每日提示:检查所有嵌套组件是否不依赖于受更改影响的某些存储变量