如何在 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
。
我知道这是一种反模式,但它会大大简化事情。此外,我只是好奇这是否可能。当我调用 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
。