vue3 父子组件的双向绑定3

应用场景:子组件数据发送改变时父组件也做出相应的改变

方法一:通过v-model实现

适用范围:数据简单的情况

思路:父组件通过v-model绑定,子组件通过 prop接收modelValue,然后通过监听该数据,再分发出去,从而实现父子组件的双向绑定。

注意:拿到modelValue不能直接修改,否则会报警告。

原因:直接修改,违背了vue的单向数据流原则,也就是父组件传过来的值在子组件中不能直接修改。

解决方法:定义个变量将modelValue做个浅拷贝保存起来,修改这个变量。

父组件

<template>
  <div>
    <son v-model="fatherData"></son>
    father数据展示 <br/>
    姓名:{{ fatherData.name }} 
    年龄:{{ fatherData.age }}
    性别:{{ fatherData.sex }}
  </div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import Son from './son.vue'
export default defineComponent({
  components: {
    Son
  },
  setup() {
    let fatherData = {
      name: '小明',
      age: 18,
      sex: '男'
    }

    return { fatherData }
  }
})
</script>
<style scoped></style>

子组件

<template>
  <div>
    姓名:<input type="text" v-model="sonData.name" /><br />
    年龄:<input type="number" v-model="sonData.age" /><br />
    性别:<input type="text" v-model="sonData.sex" />
  </div>
</template>

<script lang="ts">
import { defineComponent, watch, ref } from 'vue'

export default defineComponent({
  props: {
    modelValue: {
      type: Object,
      required: true
    }
  },
  emits: ['update:modelValue'],
  setup(props, { emit }) {
    const sonData = ref({ ...props.modelValue })
    watch(
      () => sonData,
      (newValue) => {
        console.log(newValue)

        emit('update:modelValue', newValue.value)
      },
      { deep: true }
    )
    return { sonData }
  }
})
</script>

<style scoped></style>

方式二:通过v-bind和v-on实现

这个方法和v-model本质上是一样的,因为v-model (:value+@input) 只是一中语法糖写法,拆开还是v-model和v-on

使用范围:数据及传值过程复杂或者对其数据进行其他操作时(也就是说父组件的值来自它的父组件甚至来自他的父父组件),这时使用v-model,就会出现数据丢失,没实现双向的情况。

思路:父组件依然可通过v-model(如果需要有额外的操作,父组件也需要通过v-bind和v-on绑定)来绑定值,但子组件就通过v-bind和v-on绑定。

父组件

<el-input
    v-bind="item.otherOptions"
    :model-value="modelValue[`${item.field}`]"
    @update:modelValue="handleValueChange($event, item.field)"
></el-input>

子组件

<template>
  <div>
    姓名:<el-input
      type="text"
      :modelValue="sonData.name"
      @update:modelValue="handleValueChange($event, 'name')"
    ></el-input>

    {{ modelValue.name }}
    <br />
    年龄:<input
      type="text"
      :value="sonData.age"
      @input="handleValueChanges($event, 'age')"
    /><br />
    {{ modelValue.age }}
    性别:<input
      type="text"
      :value="sonData.sex"
      @input="handleValueChanges($event, 'sex')"
    />
  </div>
</template>

<script lang="ts">
import { defineComponent, watch, ref } from 'vue'

export default defineComponent({
  props: {
    modelValue: {
      type: Object,
      required: true
    }
  },
  emits: ['update:modelValue'],
  setup(props, { emit }) {
    console.log('props', props.modelValue)
    const sonData = ref<any>({ ...props.modelValue })
    const handleValueChange = (value: any, field: string) => {
      sonData.value[field] = value
      emit('update:modelValue', { ...sonData.value, [field]: value })
    }
    const handleValueChanges = (e: any, field: string) => {
      sonData.value[field] = e.target.value
      emit('update:modelValue', { ...sonData.value, [field]: e.target.value })
    }
    return { handleValueChange, handleValueChanges, sonData }
  }
})
</script>

<style scoped></style>

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值