因为props是单向数据流,所以我们有几种方式去实现父子组件input输入框双向绑定。
方法一:props属性 + input回调
父组件 Demo
<template>
<div id="demo">
<div class="box">
<input type="text" v-model="name"/>
<demo-child v-model="name"></demo-child>
</div>
</div>
</template>
import DemoChild from '@/components/DemoChild'
export default {
data() {
return {
name:'你好呀'
}
},
components: {
DemoChild
},
}
子组件 DemoChild
<template>
<div id="demo_child">
<div class="box">
<!-- input的值绑定nameFromFather,input的值发生改变时触发change事件(input事件是输入框值发生改变的回调事件)-->
<input type="text" :value="nameFromFather" @input="change"/>
</div>
</div>
</template>
export default {
name: 'child',
//声明model,这个model就是父组件绑定的model
model:{
prop: 'nameFromFather', // 绑定的props属性,这里是'nameFromFather'
event: 'dataToFather' // 触发父组件中v-model绑定的属性发生改变的方法,名称自取
},
props:{
nameFromFather:String //自定义属性,名称自取,这个属性接收父组件传递过来的数据
},
methods: {
change(e){
//this.$emit('调用的方法即model中的event','子组件input的值')
this.$emit('dataToFather',e.target.value)
}
},
}
因为每种方法对于父组件的写法是一样的,只是子组件上有所不同,所以下面的方法我就不贴上父组件的代码了,有需要的话,直接看方法一中父组件的写法即可。
方法二:data属性 + input回调
子组件 DemoChild
<template>
<div id="demo_child">
<div class="box">
<input type="text" v-model="value" @input="change"/>
</div>
</div>
</template>
export default {
name: 'child',
//利用data数据,与input输入框的value值绑定
data(){
return {
value:this.nameFromFather //自定义属性,名称自取,使其值等于自定义的props属性
}
},
//声明model,这个model就是父组件绑定的model
model:{
prop: 'nameFromFather', // 绑定的props属性,这里是'nameFromFather'
event: 'dataToFather' // 触发父组件中v-model绑定的属性发生改变的方法,名称自取
},
props:{
nameFromFather:String //自定义属性,名称自取,这个属性接收父组件传递过来的数据
},
methods: {
change(e){
//this.$emit('调用的方法即model中的event','子组件input的值')
this.$emit('dataToFather',e.target.value)
}
},
}
其实对比下来很明显就能看到,方法一和方法二的不同就在于input输入框绑定值的方式不一样,一个是:value:nameFromFather
,一个是v-model:"value"
,那么为什么我们不直接用v-model:"nameFromFather"
呢?
其实原因很简单,因为组件props属性是单向数据流,如果它既接收父组件的数据又改变父组件的数据,那么数据绑定这块就乱套了,到底谁是初始数据就说不清楚了,所以vue把v-model绑定props属性的这种使用方式做了报错处理。
v-model=”props属性“.png
仔细看报错图片"Instead..."
后面那串,其实我们的方法二和方法三就是上面描述的方法,"use a data or computed property based on the prop's value"
方法三:data属性+watch监听
子组件 DemoChild
<template>
<div id="demo_child">
<div class="box">
<input type="text" v-model="value" />
</div>
</div>
</template>
export default {
name: 'child',
//利用data数据,与input输入框的value值绑定
data(){
return {
value:this.nameFromFather //自定义属性,名称自取,使其值等于自定义的props属性
}
},
watch:{
//监听value属性
value(){
//this.$emit('调用的方法即model中的event','子组件input的值')
this.$emit('dataToFather',`${this.value}`)
}
},
//声明model,这个model就是父组件绑定的model
model:{
prop: 'nameFromFather', // 绑定的props属性,这里是'nameFromFather'
event: 'dataToFather' // 触发父组件中v-model绑定的属性发生改变的方法,名称自取
},
props:{
nameFromFather:String //自定义属性,名称自取,这个属性接收父组件传递过来的数据
}
}