vue使用model属性实现父子组件v-model双向绑定数据同步访问。

参考1

参考2

关键一句话:
子组件定义props;值为fatherValue,这个值就是父组件的formData.value,子组件在data里面定义关联值childValue: this.fatherValue ,然后通过@input事件用$emit传值给父组件。 ——(注意:这里使用关联值是因为;vue的父子组件传参,子组件是不能够直接修改props的值达到父组件值也改变的效果) 所以使用子组件使用model和props转参再修改——

far.vue

<template>
  <div>
    <div>{{ formData }}--{{ userName }}</div>
    <son v-model="formData.value" :user-name="userName" />
    <button @click="changeVal">点击变化value</button>
  </div>
</template>
<script>
import son from './son.vue'
export default {
  name: 'Father',
  components: {
    son
  },
  data() {
    return {
      formData: {
        value: ''
      }, // 一个form对象 表单验证正常写法
      userName: '张三'
    }
  },
  watch: {
    value(val) {
      console.log('父组件看见的' + val)
    }
  },
  methods: {
    changeVal() {
      this.formData.value = '父组件事件改变了传值'
    }
  }
}
</script>

son.vue

<template>
  <div>
    <br>
    子组件:
    <div>{{ userName }}</div>
    <input v-model="childValue" type="text" @input="childInputChange">
  </div>
</template>
<script>

export default {
  name: 'Son',
  model: { // 定义model
    // 父组件v-model绑定的值传递给props中的fatherValue
    prop: 'fatherValue',
    // 通过emit触发childValueChange将内部值传递给父组件v-model绑定的值
    event: 'childValueChange'
  },
  props: {
    fatherValue: { // 接受父组件传递的值
      type: String,
      default: ''
    },
    userName: { // 接受父组件传递的值
      type: String,
      default: ''
    }
  },
  data() {
    return {
      childValue: this.fatherValue// 关联值
    }
  },
  watch: {
    fatherValue(val) { // 这一步重新赋值 是因为props里面的fatherValue改变了 但是data里面的childValue不会改变 从而视图不会更新
      console.log('父组件看见的' + val)
      this.childValue = val
    }
  },
  methods: {
    childInputChange() {
      // 通过$emit触发childValueChange(model内定义)事件,将内部值传递给给父组件
      this.$emit('childValueChange', this.childValue)
    }
  }
}
</script>

注意一个很诡异的问题:
父组件有个list,子组件for循环显示,并且可以删除;当使用父子组件和v-model双向绑定时候,我如果在子组件里使用this.childValue = this.childValue.filter(ele => ele !== item)去删除选中的数据,然后再选择某条数据修改字段后赋值。是会存在bug的:就是原来删除的数据又显示出来了。
在这里插入图片描述

会存在bug的删除方法如下:

    deleteItem(item) {
      this.childValue = this.childValue.filter(ele => ele !== item)
      this.$emit('changeList', this.childValue)
    }

必须改成以下splice删除才可以:

    deleteItem(item, index) {
      this.childValue.splice(index, 1)
      this.$emit('changeList', this.childValue)
    }

chatGpt解释如下:
问题出在使用 filter 方法时,它会返回一个新的数组,而不是直接修改原始数组。因此,当您使用 this.childValue = this.childValue.filter(ele => ele !== item) 时,实际上是将新的过滤后的数组赋值给了 this.childValue。这意味着 this.childValue 指向了一个全新的数组对象,而不再是原始的数组对象。这可能会导致在父组件中无法正确地获取到更新后的数组,因为父组件中的 value prop 仍然指向原始的数组对象。

另一方面, 使用 splice 方法可以直接修改原始数组,而不会创建新的数组对象。这样可以确保 this.childValue 仍然指向原始的数组对象,并且父组件中的 value prop 也会正确地获取到更新后的数组。
因此,虽然在某些情况下使用 filter 方法可能没有问题,但在涉及到需要更新父组件中的 prop 值时,使用 splice 方法可以更可靠地确保更新后的数组能够正确地传递给父组件。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值