如何在 Vue3 中改变道具并调用 parent 计算的 setter

How to mutate props in Vue3 and have the parent computed setter called

我知道这是一种反模式,但它会大大简化事情。此外,我只是好奇这是否可能。当我调用 test1() 时,我收到以下警告:Set operation on key "items" failed: target is readonly. 并且没有其他任何反应。当我在 child 和 parent 中调用 test2() items 更改时,但未调用计算的 setter。为什么?

为什么不调用计算的 setter?是否可以改变 child 中的道具并仍然调用计算的 setter?

我有以下 parent 组件:

<template>
  <div class="m-10 bg-white">
    parent: {{ items }}
    <br />
    <br />
    <TestComponent2 :items="items" />
  </div>
</template>

<script lang="ts" setup>
import { computed, ref } from "vue";
import TestComponent2 from "./TestComponent2.vue";

const container = ref({
  items: ["a", "b", "c"],
});

const items = computed({
  get: () => {
    return container.value.items;
  },
  set: (v) => {
    console.log("set", v);
    container.value.items = v;
  },
});
</script>

这是 child 组件:

<template>
  <div>
    child: {{ items }}
    <br />
    <br />
    <button @click="test1()">test1</button>
    <br />
    <button @click="test2()">test2</button>
  </div>
</template>

<script lang="ts" setup>
import { defineProps, toRefs } from "vue";

const props = defineProps({
  items: {
    type: Array,
    required: true,
  },
});

const { items } = toRefs(props);

const test1 = () => {
  items.value = [];
};

const test2 = () => {
  items.value.pop();
};
</script>

您可能正在寻找 v-model:items="items"

要点:

parent.vue:

<child v-model:items="items" />

child.vue:

emit('update:items', value);

注意: items.pop()items.push() 都会改变父项和子项中的值,但它们不会触发赋值。

为此,您必须:

const copy = [...items];
copy.push('new'); // or pop(), splice()...
// if inside child:
emit('update:items', copy);

文档here

工作示例here


技术上,

<child v-model:items="items" />

是 shorthand 用于:

<child
  :items="items"
  @update:items="value => items = value"
/>

如果您没有指定子变量名称(在我们的例子中是 items),它默认为 modelValue