Vue子组件道具不更新

问题描述 投票:0回答:1

在其他所有的问题中,我都能找到数据被使用,防止反应性。这里的数据没有被使用,道具本身在渲染中没有更新。

我的VueX函数是

addItemColumn() 在第一个盒子里创建一个新的列,本质上盒子不允许自己成长;但是,父代可以要求添加一个新的列(到第一个盒子里)。

MoveBoxDown() 应该是不言自明的,但会将当前的方框(该函数被调用)与下面的方框进行切换。

下面是发生了什么...

当只执行 item 列时,一个带有默认项目的额外列被正确添加并重新渲染。然而,当首先执行moveBoxDown时,发生的情况是盒子正确切换并重新渲染,但当我去执行addItemColumn时,子项目Box没有看到任何更新。

奇怪的是,1) addItemColumn() 作品和演绎2) moveBoxDown() 作品和演绎

所以不会出现更新moveBoxDown失败传播导致addItemColumn的问题。事实上,运行 moveBoxDown() 与我的任何其他突变完美地工作。

3) Vue Devtools显示Box已经更新,对于这个问题 box.items 更新4) 根据示例代码 <p>{{ box.items.length }}<p> 的更新,而不是子代的Box。

如果它在父代中不起作用,我可能会认为是子代的键入问题;然而,它确实如此,并且结合devtools正确显示更新的 box 在我看来,由于某种未知的原因,子代似乎没有检测到道具已被更新?

我能想到的唯一的解决方法是把Box变成一个有槽的组件,因为父体是知道的,这似乎可以缓解这个问题。

我在VueX中拥有以下数据结构

Boxes = [
  {
    id: number
    items: [
      {
        id: number
        properties: {
          ...
        }
      },
      ...
    ]
  },
  ...
]

一个项目正在被添加使用 .push() 在VueX中,由 addBox 这样就能检测到变化。同样,在一般情况下,这样做是可行的,但也有拒绝更新的情况,即使Vue开发工具显示了正确的,现在更新的道具值。

父级

<template>
  <b-button @click="addBox()">Add Box</b-button>

  <div v-for="(box, index) in boxes" :key="`box_${index}`">
    <!-- This updates so is not related to the parents loop -->
    <p>{{ box.items.length }}</p>
    <Box :box="box" />
  </div>
</template>

<script>
// Import VueX
import { mapGetters, mapActions } from "vuex";

// Import Components
import Box from "~/components/Box";

export default {
  name: "BoxesPage",
  layout: "BoxesLayout",
  components: { Box },
  computed: {
    ...mapGetters({
      boxes: "items/boxes"
    })
  },
  methods: {
    ...mapActions({
      addItemColumn: "items/addItemColumn"
    })
  },
  async fetch({ store, params }) {
    await store.dispatch("items/getInventory");
  }
};
</script>

盒子

<template>
  <div>
    <!-- Neither of these update either, so this is not related to the child's loop -->
    <p>{{ box }}<p>
    <p>{{ box.items.length }}<p>
    <b-button
      @click="moveBoxDown()"
      icon-right="chevron-down"
    />
    <div
      v-for="item in box.items"
      :key="
      `box_${box.index}_item_${item.index}_${item.name}`"
    >
      <!-- This does not add a new item -->
      <Item :item="item" />
    </div>
  </div>
</template>

<script>
// Import VueX
import { mapGetters, mapActions } from "vuex";

// Import Components
import Item from "~/components/Item";

export default {
  name: "Box",
  components: { Item },
  props: {
    Box: {
      type: Object,
      required: true
    }
  },
  methods: {
    ...mapActions({
      moveBoxDown: "items/moveBoxDown",
    })
  }
};
</script>

我不会附上VueX的行文,因为VueX的实现似乎又是完全没有问题的......不管它是否正确地重新渲染,Vue开发工具都显示该道具被正确地更新了。

编辑:VueX" items.js"

export const state = () => ({
  boxes: []
});

export const actions = {
  moveFrameDown({ commit }, frameIndex) {
    commit('switchBoxes', { fromIndex: frameIndex, toIndex: frameIndex + 1 });
  },
  addBoxColumn({ commit }, item) {
    // Item is a default item type
    commit('newItemColumn', item);
  },
}

export const mutations = {
  SwitchBoxes: (state, { fromIndex, toIndex }) => {
    state.boxes[fromIndex] = {
      index: fromIndex,
      items: state.boxes.splice(toIndex, 1, {
        index: toIndex,
        items: state.frames[fromIndex].items
      })[0].items
    };
  },
  newItemColumn: (state, itemProps) => {
    state.boxes[0].items.push({
      id: state.idCounter
      props: itemProps
    });
    state.idCounter += 1;
  }
};
vue.js nuxt.js
1个回答
3
投票

你的例子不是很简陋,所以我只能猜测可能是什么原因。

这是个危险的信号。

state.boxes[fromIndex] = { ... }

从... 文件:

Vue无法检测到以下对数组的更改。

  1. 当你 直接设置一个索引的项目,例如 vm.items[indexOfItem] = newValue
  2. 当你修改数组的长度时,比如说。vm.items.length = newLength

你也在做一个 splice() 数组上,Vue可以检测到,所以恰好数组的变化可能会反映在视图中,然而你可能没有意识到的是,你分配给数组索引的新对象不会被反应。

你需要使用 Vue.set():

Vue.set(state.boxes, fromIndex, { ... })
© www.soinside.com 2019 - 2024. All rights reserved.