Vue watch、computed、toRef、onMounted 解构 props 简单应用场景
props.detailData 是父控件传的值,如何将 detailData 中的 custodyNo 赋值给 formData 中的 reason
父控件
<Detail v-model="detailVisible" :detailData="currentDetailData" />
子控件
const props = defineProps({
detailData: {
type: Object,
default: () => ({}), // 默认空对象,避免 undefined
},
});
const formData = reactive({
status: 1,
reason: props.detailData.CustodyNo,
});
在 Vue 3 中,你可以使用 watch 来监听 props.detailData 的变化,并在变化时将 custodyNo 赋值给 formData.reason。以下是实现方式:
import { reactive, watch } from 'vue';
const props = defineProps({
detailData: {
type: Object,
default: () => ({}), // 默认空对象,避免 undefined
},
});
const formData = reactive({
status: 1,
reason: props.detailData.custodyNo || '', // 初始赋值
});
// 监听 props.detailData 的变化
watch(
() => props.detailData,
(newDetailData) => {
formData.reason = newDetailData.custodyNo || '';
},
{ deep: true, immediate: true } // deep: 深度监听对象变化,immediate: 立即执行一次
);
注意事项:
- 我注意到你在代码中使用了
CustodyNo(大写开头),但在问题描述中写的是custodyNo(小写开头)。请确保属性名大小写一致。 watch的deep: true选项确保能监听到对象内部属性的变化。immediate: true选项会在组件创建时立即执行一次回调,确保初始值被正确设置。- 添加了
|| ''作为后备值,避免在custodyNo为 undefined 时出现问题。
如果你的属性名确实是 CustodyNo(大写开头),则应该修改为:
formData.reason = newDetailData.CustodyNo || '';
除了使用 watch,还有以下几种方法可以将 props.detailData.custodyNo 赋值给 formData.reason:
方法 1:使用 toRef 或 computed(推荐)
如果 formData.reason 需要始终同步 props.detailData.custodyNo,可以使用 computed 或 toRef(适用于 Vue 3.2+)。
(1)使用 computed
import { reactive, computed } from 'vue';
const props = defineProps({
detailData: {
type: Object,
default: () => ({}),
},
});
const formData = reactive({
status: 1,
reason: computed(() => props.detailData.custodyNo || ''), // 自动同步
});
特点:
formData.reason会随props.detailData.custodyNo自动更新。- 但
formData.reason会变成readonly,不能直接修改(除非结合setter)。
(2)使用 toRef(Vue 3.2+)
import { reactive, toRef } from 'vue';
const props = defineProps({
detailData: {
type: Object,
default: () => ({}),
},
});
const formData = reactive({
status: 1,
reason: toRef(props.detailData, 'custodyNo'), // 直接引用
});
特点:
formData.reason直接引用props.detailData.custodyNo,修改reason会影响detailData(除非detailData是只读的)。- 适用于需要双向绑定的情况。
方法 2:在 onMounted 或 setup 中初始化
如果 detailData 只初始化一次(不会动态变化),可以直接在 setup 或 onMounted 里赋值:
import { reactive, onMounted } from 'vue';
const props = defineProps({
detailData: {
type: Object,
default: () => ({}),
},
});
const formData = reactive({
status: 1,
reason: props.detailData.custodyNo || '', // 初始化
});
// 如果父组件可能异步传值,可以在 onMounted 里再检查一次
onMounted(() => {
if (props.detailData.custodyNo) {
formData.reason = props.detailData.custodyNo;
}
});
特点:
- 适用于
detailData不会动态变化的情况。 - 如果父组件是异步加载数据,可能需要结合
watch或onUpdated监听变化。
方法 3:使用 v-model + 计算属性(双向绑定)
如果希望 formData.reason 既能接收 props.detailData.custodyNo,又能修改并通知父组件,可以使用 v-model + computed 的 get/set:
import { computed } from 'vue';
const props = defineProps({
detailData: {
type: Object,
default: () => ({}),
},
});
const emit = defineEmits(['update:detailData']);
const formData = reactive({
status: 1,
reason: computed({
get: () => props.detailData.custodyNo || '',
set: (value) => {
emit('update:detailData', { ...props.detailData, custodyNo: value });
},
}),
});
特点:
- 适用于需要双向绑定的情况(子组件修改
reason能同步到父组件)。 - 父组件需要用
v-model或:detailData.sync方式传值。
方法 4:直接解构 props(适用于简单场景)
如果 formData 只需要 detailData 的某些字段,可以解构 props:
const props = defineProps({
detailData: {
type: Object,
default: () => ({}),
},
});
const formData = reactive({
status: 1,
...pick(props.detailData, ['custodyNo']), // 直接解构
});
特点:
- 适用于
formData和detailData结构相似的情况。 - 但无法自动更新(除非结合
watch或computed)。
总结
| 方法 | 适用场景 | 是否自动更新 | 是否可修改 |
|---|---|---|---|
watch |
监听变化 | ✅ | ✅ |
computed |
只读依赖 | ✅ | ❌(除非用 setter) |
toRef |
直接引用 | ✅ | ✅(可能影响父组件) |
onMounted |
初始化赋值 | ❌ | ✅ |
v-model + computed |
双向绑定 | ✅ | ✅ |
解构 props |
简单映射 | ❌ | ✅ |
推荐:
- 如果只是 单向同步(子组件只读),用
computed。 - 如果需要 双向绑定,用
v-model+computed的get/set。 - 如果
detailData不会变化,直接用onMounted或setup初始化。
本文来自博客园,作者:VipSoft 转载请注明原文链接:https://www.cnblogs.com/vipsoft/p/19046540
浙公网安备 33010602011771号