【问题标题】:Issue with computed state and mutated state with Vue.jsVue.js 的计算状态和变异状态问题
【发布时间】:2019-02-07 12:21:26
【问题描述】:

我发现从 Vuex 状态管理设置的绑定组件存在问题。

我有如下状态存储:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    id: 0,
    contentBlocks: []
  },
  mutations: {
    addContentBlock(state, contentBlock) {
      contentBlock.id = state.id
      state.contentBlocks.push(contentBlock)
      state.id += 1
    },
    updateContentBlock(state, contentBlock) {
      const index = state.contentBlocks.findIndex(block => block.id === contentBlock.id)
      Vue.set(state.contentBlocks, index, contentBlock)
    },
    removeContentBlock(state, contentBlock) {
      const index = state.contentBlocks.findIndex(block => block.id === contentBlock.id)
      Vue.delete(state.contentBlocks, index)
    }
  }
})

然后我在baseComponent.vue 中循环state.contentBlocks,如下所示:

<v-container pa-0 v-for="(contentBlock, index) in contentBlocks" v-bind:key="contentBlock.index">
  <component v-bind:is="contentBlock.blockComponent" v-bind:contentBlock="contentBlock"></component>
</v-container>

然后我通过添加、更新和删除内容块来改变state.contentBlocks。 (我从基础组件中添加块,从绑定到&lt;component&gt;&lt;/component&gt; 的子组件中删除和更新。

我在BaseComponent.vue 中使用get 突变的state.contentBlocksBaseComponent.vue

computed: {
    contentBlocks: () => store.state.contentBlocks,
}

更新时,我在控制台中看到以下内容:

一切看起来都很好。然后我去删除索引 1 处的块,它在状态级别“工作”:

但是 DOM 并没有发挥作用:

(!!) 上面,0和2的索引是正确的,但是索引2的内容是被删除的索引1的内容(!!?)救命! :D

【问题讨论】:

    标签: javascript vue.js vuex


    【解决方案1】:

    baseComponent.vue 中,使用计算属性来循环内容块而不是 vuex 存储的状态:

    <v-container pa-0 v-for="(contentBlock, index) in blocks" v-bind:key="contentBlock.index">
      <component v-bind:is="contentBlock.blockComponent" v-bind:contentBlock="contentBlock"></component>
    </v-container>
    
    computed: {
      blocks () {
        return this.$store.getters['contentBlocks']
      }
    }
    

    您还需要将相应的 getter 添加到商店:

    export default new Vuex.Store({
      state: {
        id: 0,
        contentBlocks: []
      },
      getters: {
        contentBlocks: (state) => state.contentBlocks 
      }
      mutations: {
        addContentBlock(state, contentBlock) {
          contentBlock.id = state.id
          state.contentBlocks.push(contentBlock)
          state.id += 1
        },
        updateContentBlock(state, contentBlock) {
          const index = state.contentBlocks.findIndex(block => block.id === contentBlock.id)
          Vue.set(state.contentBlocks, index, contentBlock)
        },
        removeContentBlock(state, contentBlock) {
          const index = state.contentBlocks.findIndex(block => block.id === contentBlock.id)
          Vue.delete(state.contentBlocks, index)
        }
      }
    })
    

    不相关,但您可以简单地将removeContentBlock 突变为:

    state.contentBlocks = state.contentBlocks.filter({id} => id !== contentBlock.id)
    

    更新

    component 元素上添加一个键:

    <v-container pa-0 v-for="(contentBlock, index) in blocks" v-bind:key="contentBlock.index">
      <component v-bind:is="contentBlock.blockComponent" v-bind:contentBlock="contentBlock" :key="contentBlock.id"></component>
    </v-container>
    

    【讨论】:

    • 不知道谁反对此投票(我会为提供帮助的感激之情投票,这似乎有点苛刻)。我很欣赏这方面的努力,希望它能奏效,但不幸的是,同样的行为发生了......删除时 DOM 保留了旧内容,但删除了正确的密钥......
    • 我也做了同样的事情,报告了他们两个,并标记了对上一个问题的奇怪评论。回到问题 - 这似乎是更新 DOM 的一个基本问题?删除时,更新的值字段(标记为data-v-770f4dcd)保留而另一个离开?真的让我摸不着头脑......
    • 我相信这是因为动态组件以及 Vue 将如何尝试重用组件。添加一个关键属性应该可以解决它。答案也已更新。
    • 轰隆隆!您的更新工作完美。我的代码现在可以完美运行了!非常感谢。
    • 乐于助人!干杯!
    猜你喜欢
    • 2020-12-20
    • 2016-11-18
    • 2019-02-13
    • 1970-01-01
    • 2020-09-19
    • 1970-01-01
    • 2019-01-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多