VUE3 父子组件数据双向同步方法 ——有点神奇的新方法


theme: devui-blue

前言

今天在封装一个组件时,意外发现一个使父子组件数据双向同步的一种新方法,不使用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>

运行效果

动画5.gif

解析

image.png

经过测试发现,必须在子组件中使用immediate:true后才能实现 父子组件的form数据同步,
而且经过打印发现,除了第一次数据监听,后续赋值时可发现 localForm.value === newVal 为true意味着两个对象共享一个内存,那么可以理解在使用immediate:true时,子组件在watch赋值时,可以达到父子组件中prop对应的这个对象指向一个内存,从而实现数据同步。

总结

vue中的prop设计是单向数据流的设计理念,但是有时候我们在封装组件时特别是复杂的组件,传入的prop也是个复杂的对象而且想要达到数据双向绑定的效果时,常用的做法是使用emit(‘update:form’)这种方式。现在这种使用watch的方式,相对简单一些。不过,不知道有没有什么其他问题产生?

最后也想问一下观看文章的人,能不能阐述一下原理,或者vue源码中是否有答案?

© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容