vue3 子组件可以修改props的属性值吗? 可以修改
1.概要
最近做项目的时候,遇到个问题,父组件直接修改子组件的data数据.于是在思考子组件是否可以修改父组件?
答案:可以的,不区分数据类型
2.父调子
//子组件
let items = reactive({
select: [
{
key: 1,
value: "",
id: 1, // 必须存在,否则不可拖拽
},
],
});
const getItems = () => {
return items;
};
const resetItems = () => {
items.select = [
{
key: 1,
value: "",
id: 1, // 必须存在,否则不可拖拽
},
];
};
defineExpose({
getItems,
resetItems,
items
});
//父组件 可以通脱refs调用,也可以直接赋值 xAxisFieldRef.value.items.select
xAxisFieldRef.value.getItems.select = data
.filter((x) => x.selectType === 1)
.map((x, index) => {
return {
key: index + 1,
value: x.fieldName,
id: index + 1,
};
});
3.子调父
// 父组件
<props-test
v-model="model"
:name="refName"
:user="retUser"
:attrs1="retUser"
></props-test>
父组件基础类型{{ model }} 父组件引用类型{{ retUser }}
setup() {
const state = {
title: "vue3.0 demo",
};
const model = ref("aa");
const refName = ref(0);
const retUser = reactive({
name: "gg",
});
return { state, model, refName, retUser };
},
//子组件
<template>
<div>
<button @click="submit">测试基础类型 {{ props.modelValue }}</button>
<button @click="direct">测试引用类型 {{ props.user }}</button>
</div>
</template>
<script>
import { defineComponent } from "vue";
export default defineComponent({
name: "propsTest",
props: {
modelValue: String,
name: String,
user: Object,
info: Object,
},
emits: ["update:modelValue"],
setup(props, context) {
console.log("props-text", props);
console.log("props-ctx", context);
// 使用 emit 修改
const submit = () => {
// context.emit("update:modelValue", new Date()); // 基础类型需要使用 emit 来修改
props.modelValue = new Date(); // 直接手动修改无效
};
// 使用 proxy 修改
const user = props.user; // 可以直接获取,不需要使用 toRef
const direct = () => {
user.name = new Date();
};
return {
submit,
direct,
props,
};
},
});
</script>
4.本质
- 基本数据类型:副本,不会影响数据的修改
如何修改?
context.emit("update:modelValue", new Date()); // 基础类型需要使用 emit 来修改
- 引用数据类型:地址,会影响数据的修改
如何修改?
// 使用 proxy 修改
const user = props.user; // 可以直接获取,不需要使用 toRef
const direct = () => {
user.name = new Date();
};
5.总结
- vue是单向数据流,父子组件却可以互相修改,官方不建议子组件修改props属性
- props属性最终来源于父组件的data属性
- 本质:区分js类型的差异
- 基本类型需要用emit触发修改
- 引用类型可以通过reactive直接修改