简体   繁体   English

使用 Lodash.remove 通过 Vuex 突变更改 state 不会触发我的 Vue 组件中的反应性重新渲染

[英]Changed state through Vuex mutation using Lodash.remove does not trigger a reactive re-render in my Vue component

I have a component that receives an array of Villager into it's prop from a parent component.我有一个组件,它从父组件接收一组Villager到它的prop中。 The parent component pulls that array from this.$store.state .父组件从this.$store.state中提取该数组。

return this.$store.state.villages.find(value => value.id === 0).villagers

I execute a this.$store.mutation commit to alter the given array afterwards.之后我执行this.$store.mutation提交来更改给定的数组。 The mutation does work as you can see in the screenshot further down.正如您在下面的屏幕截图中看到的那样,突变确实有效。 However the component I am in is not re-rendering and is still showing 3 instead of 2 items.但是,我所在的组件没有重新渲染,并且仍然显示 3 而不是 2 项。

The reactive chain seems to be broken somewhere but I can not pinpoint the fiend.反应链似乎在某处被打破,但我无法确定恶魔。 I thought the props value is a reactive mechanism.我认为props值是一种反应机制。 As you can see in the screenshot it's value has changed but the DOM was not updated accordingly.正如您在屏幕截图中看到的,它的值已更改,但 DOM 并未相应更新。

在此处输入图像描述

Code Excerpts代码摘录

I tried to extract the relevant parts for the questions我试图提取问题的相关部分

store/index.ts存储/索引.ts

[...]
export default new Vuex.Store({
  state: {
    villages: [
      {
        id: 0,
        name: 'Peniuli',
        foundingDate: 20,
        villagers: [
          {
            id: '33b07765-0ec6-4600-aeb1-43187c362c5a1',
            name: 'Baltasar',
            bloodline: 'Gent',
            occupation: 'Farmer'
          },
[...]
   mutations: {
       disbandVillager (state, payload) {
         const villagerId = payload.id
         const village = state.villages.find(value => value.id === 0)
         console.debug('disbanding villager:', villagerId)
         if (!_.isNil(village)) {
           console.debug('bfore:', village.villagers)
           _.remove(village.villagers, function (n) {
             return n.id === villagerId
           })
           console.debug('after:', village.villagers)
         }
       }
     },
[...]

Village.vue村庄.vue

<template>
    <Villagers :villagers="playerVillage.villagers"></Villagers>
</template>
[...]
  computed: {
    playerVillage: function () {
      return this.$store.state.villages.find(value => value.id === 0)
    }
  }
[...]

Villagers.vue村民.vue

<template>
  <v-container>
    <v-card v-for="villager in villagers" :key="villager.id">
      <v-row>
        <v-col>
          <v-card-title>Name: {{villager.name}}</v-card-title>
        </v-col>
        <v-col>
          <v-card-title>Bloodline: {{villager.bloodline}}</v-card-title>
        </v-col>
        <v-col>
          <v-card-title>Occupation: {{villager.occupation}}</v-card-title>
        </v-col>
        <v-col v-if="managable">
          <DisbandButton :villager="villager"></DisbandButton>
        </v-col>
      </v-row>
    </v-card>
  </v-container>
</template>

<script>
import DisbandButton from '@/components/village/DisbandButton'

export default {
  name: 'Villagers',
  components: { DisbandButton },
  props: [
    'villagers',
    'managable'
  ]
}
</script>

DisbandButton.vue DisbandButton.vue

<template>
  <v-btn @click="disbandVillager" color="red">Disband</v-btn>
</template>

<script>
export default {
  name: 'DisbandButton',
  props: ['villager'],
  methods: {
    disbandVillager: function () {
      this.$store.commit('disbandVillager', { id: this.villager.id })
    }
  }
}
</script>

Assuming that's lodash then I believe the problem is that you're using _.remove .假设那是 lodash 那么我相信问题在于您正在使用_.remove

Internally _.remove is implemented in such a way that it doesn't trigger Vue's reactivity system.在内部_.remove的实现方式不会触发 Vue 的反应系统。 Specifically here:具体在这里:

https://github.com/lodash/lodash/blob/ded9bc66583ed0b4e3b7dc906206d40757b4a90a/lodash.js#L3859 https://github.com/lodash/lodash/blob/ded9bc66583ed0b4e3b7dc906206d40757b4a90a/lodash.js#L3859

That's using the default Array splice method, not the custom override provided by Vue.那是使用默认的 Array splice方法,而不是 Vue 提供的自定义覆盖。

Something like this should work:像这样的东西应该工作:

village.villagers = village.villagers.filter(function (n) {
  return n.id !== villagerId
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Nuxt Vue.js:Vuex 全局 state 更改不会触发 v-for 循环中的重新渲染组件 - Nuxt Vue.js: Vuex global state change does not trigger re-render component in v-for loop 使用 useLocalStorage 时,本地状态不会重新渲染组件 - Local state does not re-render the component when using useLocalStorage 状态更改时组件无法重新渲染 - Component not able to re-render when state is changed 如何在其数据(和状态)完好无损的情况下重新渲染组件(Vue)? - How to re-render a component (Vue) with its data (and state) intact? 更改父状态后如何重新呈现子组件? - How to re-render child component when Parent state is changed? 父组件状态改变,子组件不重新渲染 - State changed in parent component, child components do not re-render 将状态设置为空字符串不会为我触发重新渲染? - Setting state to empty string does not trigger a re-render for me? 尽管Redux状态已更新,但组件未重新渲染 - Component does not re-render although redux state is updated 为什么使用React Hooks,MomentJS对象和时间间隔/超时更新状态不会触发重新渲染? - Why does updating state using React Hooks, MomentJS object and interval/timeout not trigger re-render? React Native for Web:当 state 更新时,我的组件不会重新渲染 - React Native for Web: My component does not re-render when state is updated
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM