单向数据流
单向数据流是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>