VUE3 父子组件数据双向同步方法 ——有点神奇的新方法
前言
今天在封装一个组件时,意外发现一个使父子组件数据双向同步的一种新方法,不使用emit的方法就可以使prop传入的对象form达到父子组件数据同步。 话不多说,先看例子:
子组件代码
<!--Watch测试-->
<template>
<div>
子组件
<input type="text" v-model="localForm.name" />
<h1>子组件:{{ name }}</h1>
</div>
</template>
<script lang="ts" setup>
import { computed, ref, watch } from 'vue'
const props = defineProps<{
form: any
}>()
const localForm = ref<any>({
name: '小芳'
})
watch(
() => props.form,
(newVal, oldVal) => {
console.log('子组件newVal', newVal)
console.log('子组件oldVal', oldVal)
console.log('子组件localForm', localForm.value === newVal)
if (localForm.value !== newVal) localForm.value = newVal
},
{
deep: true,
immediate: true
}
)
let name = computed(() => {
return localForm.value.name
})
</script>
<style lang="scss" scoped></style>
父组件代码
<template>
<WatchTest :form="form"></WatchTest>
<h1>父组件:{{ name2 }}</h1>
</template>
<script lang="ts" setup>
import { computed, ref, watch } from 'vue'
import WatchTest from './components/WatchTest.vue'
const form = ref({
name: '小芳',
age: 18
})
let name2 = computed(() => {
return form.value.name
})
watch(
() => form.value,
(newVal, oldVal) => {
console.log('父组件newVal', newVal)
console.log('父组件oldVal', oldVal)
},
{
deep: true,
immediate: true
}
)
</script>
运行效果
解析
经过测试发现,必须在子组件中使用immediate:true后才能实现 父子组件的form数据同步, 而且经过打印发现,除了第一次数据监听,后续赋值时可发现 localForm.value === newVal 为true意味着两个对象共享一个内存,那么可以理解在使用immediate:true时,子组件在watch赋值时,可以达到父子组件中prop对应的这个对象指向一个内存,从而实现数据同步。
总结
vue中的prop设计是单向数据流的设计理念,但是有时候我们在封装组件时特别是复杂的组件,传入的prop也是个复杂的对象而且想要达到数据双向绑定的效果时,常用的做法是使用emit('update:form')这种方式。现在这种使用watch的方式,相对简单一些。不过,不知道有没有什么其他问题产生?
最后也想问一下观看文章的人,能不能阐述一下原理,或者vue源码中是否有答案?
转载自:https://juejin.cn/post/7171107972490199054