vue 通过 v-model 实现父子组件的双向数据绑定
转载
单向数据流
单向数据流是Vue组件一个非常明显的特征,不应该在子组件中直接修改props的值
- 如果传递的props仅仅用作展示,不涉及修改,则在模板中直接使用即可
- 如果需要对props的值进行转化然后展示,则应该使用computed计算属性
- 如果props的值用作初始化,应该定义一个子组件的data属性并将props作为其初始值
组件之间的通信
- 父子组件的关系可以总结为
props
向下传递,事件event
向上传递 - 祖先组件和后代组件(跨多代)的数据传递,可以使用
provide
和inject
来实现 - 跨组件或者兄弟组件之间的通信,可以通过
eventBus
或者vuex
等方式来实现
通过v-model语法糖实现父子组件的数据双绑
Vue
内置了v-model
指令,v-model
是一个语法糖,默认会利用名为 value
的 prop
和名为input
的event
。model
属性可以自定义prop
和event
model: {
prop: 'msg',
event: 'cc'
},
父组件test的值将会传入这个名为msg的prop
同是当aa组件触发click事件并附带一个新的值得时候,父组件的test属性将会被更新
//父组件
<template>
<div>
<aa class="abc" v-model="test" ></aa>
{{'外面的值:' + test}}
<button @click="fn">外面改变里面</button>
</div>
</template>
<script>
import aa from './aa'
export default {
data () {
return {
test: ''
}
},
methods: {
fn () {
this.test += 1
}
},
components:{
aa
}
}
</script>
//子组件
<template>
<div>
{{'里面的值:'+ msg}}
<button @click="fn2">里面改变外面</button>
</div>
</template>
<script>
export default {
/**
* 使用model, 这里有2个属性
* prop属性说,父组件的v-model的值就是msg
* event说,我emit ‘cc’ 的时候,父组件v-model的值就是参数的值
*/
model: {
prop: 'msg',
event: 'cc'
},
props: {
msg: ''
},
methods: {
fn2 () {
this.$emit('cc', this.msg+2)
}
}
}
</script>
//使用默认prop、event的子组件
<template>
<div>
{{'里面的值:'+ value}}
<button @click="fn2">里面改变外面</button>
</div>
</template>
<script>
export default {
/**
* 默认会利用名为 value 的 prop 和名为input的event
*/
props: {
value: ''
},
methods: {
fn2 () {
this.$emit('input', this.value+2)
}
}
}
</script>
父子组件中需要多个双向绑定写法
//父组件
<template>
<div>
<aa class="abc" v-model="sObj" ></aa>
{{'外面的值:' + test+','+touchStartTest}}
<button @click="fn" @touchstart="fnTouchstart">外面改变里面</button>
</div>
</template>
<script>
import aa from './v-model-child'
export default {
data () {
return {
test: '',
touchStartTest:'',
sObj:'',
}
},
watch:{
test:function(val){
this.sObj = JSON.stringify({test:val,touchStartTest:this.touchStartTest})
},
touchStartTest:function(val){
this.sObj = JSON.stringify({test:this.test,touchStartTest:val})
},
sObj:function(val){
this.test = JSON.parse(this.sObj).test;
this.touchStartTest = JSON.parse(this.sObj).touchStartTest;
}
},
methods: {
fn () {
this.test += 1
},
fnTouchstart(){
this.touchStartTest+=5
}
},
components:{
aa
}
}
</script>
//子组件
<template>
<div>
{{'里面的值:'+ jsonMsg.test+','+jsonMsg.touchStartTest}}
<button @click="fn2" @touchstart="fnTouchstart2">里面改变外面</button>
</div>
</template>
<script>
export default {
/**
* 使用model, 这里有2个属性
* prop属性说,父组件的v-model的值就是msg
* event说,我emit ‘cc’ 的时候,父组件v-model的值就是参数的值
*/
model: {
prop: 'msg',
event: 'cc'
},
props:['msg'],
computed:{
jsonMsg(){
return this.msg=='' ? {test:'',touchStartTest:''} : JSON.parse(this.msg);
}
},
methods: {
fn2 () {
this.$emit('cc', JSON.stringify({test:this.jsonMsg.test+2,touchStartTest:this.jsonMsg.touchStartTest}))
},
fnTouchstart2(){
this.$emit('cc', JSON.stringify({test:this.jsonMsg.test,touchStartTest:this.jsonMsg.touchStartTest+6}))
}
}
}
</script>