props
在Vue3中,当将对象或数组props
作为子组件传递时,无法更改对象或数组本身,但可以更改对象或数组的嵌套属性。
当传递单个值作为 props 时
如果将单个值作为 props
传递,则更改子组件中的 props
值将不会反映父组件中的更改。这是因为 props
是单值的,因此子组件中的更改将被视为与局部变量的更改相同。
<script setup lang="ts">
const props = defineProps(['hoge'])
// 警告:props是只读
props.hoge = 'bar'
</script>
当传递对象或数组作为 props 时
如果将对象或数组作为 props
传递,则子组件无法直接修改父组件传递的对象或数组的属性。但是,如果对象或数组属性发生更改,Vue3 将检测到更改并更新父组件的数据。
<script setup lang="ts">
interface MyObject {
name: string;
age: number;
hobbies: string[];
}
const props = defineProps({
myObject: {
type: Object as () => MyObject,
required: true,
},
});
const changeHobbies = () => {
// 可以更改通过 props 从父级接收到的 myObject 的属性
props.myObject.hobbies.push('baking');
};
</script>
<template>
<div>
<p>{{ myObject.name }}</p>
<p>{{ myObject.age }}</p>
<ul>
<li v-for="hobby in myObject.hobbies" :key="hobby">{{ hobby }}</li>
</ul>
<button @click="changeHobbies">Change Hobbies</button>
</div>
</template>
可能出现的问题
这些规范允许子组件影响父组件的状态...... 下面的官方文档还指出,最好的做法是避免此类更改,除非设计在父子之间紧密耦合,因为这使得以后很难确定数据流。 https://cn.vuejs.org/guide/components/props.html
如何将对象/数组作为 props 传递以避免意外的数据流
可以举出一个最佳实践的例子:
<script setup lang="ts">
import { defineProps, ref, Ref } from 'vue';
interface HogeObject {
name: string;
age: number;
}
const props = defineProps({
arrHoge: {
type: Array as () => Array<number | string>,
required: true,
},
objHoge: {
type: Object as () => HogeObject,
required: true,
},
});
//使用扩展语法扩展为新数组
const arrHoge: Ref<Array<number | string>> = computed(() => [...props.arrHoge]);
const objHoge: Ref<HogeObject> = computed(() => ({ ...props.objHoge }));
</script>
<template>
<div>
<p>Array: {{ arrHoge }}</p>
<p>Object: {{ objHoge }}</p>
</div>
</template>
这段代码将arrHoge
和objHoge
定义为计算为新数组和新对象的值。这样,即使 props.arrHoge
和 props.objHoge
值发生变化,arrHoge
和 objHoge
也将始终引用新的数组和新的对象。
评论(0)