关键一句话:
子组件定义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
方法可以更可靠地确保更新后的数组能够正确地传递给父组件。