单向数据流
- 单向数据流是Vue组件一个非常明显的特征,不应该在子组件中直接修改props的值
组件之间的通信
- 父子组件的关系可以总结为
prop
向下传递,事件event
向上传递 - 祖先组件和后代组件(跨多代)的数据传递,可以使用
provide
和inject
来实现 - 跨组件或者兄弟组件之间的通信,可以通过
eventBus
或者vuex
等方式来实现
封装的组件如何实现v-model的数据双绑的效果
以下两种通常是我们的实现方式, 看着就很麻烦
- 通过emit将事件派发到父组件,prop将数据传到子组件
// 子组件
<template>
<div>
<van-button @click="add" type="default">加一</van-button>
<div>
{{countsVal}}
</div>
<van-button @click="reduce" type="default">减一</van-button>
</div>
</template>
<script>
export default {
props: {
value: Number
},
data () {
return {
// props的初始化比data的初始化要靠前
countsVal: this.value
}
},
methods: {
add () {
this.countsVal++
this.$emit('add', this.countsVal)
},
reduce() {
this.countsVal--
this.$emit('reduce', this.countsVal)
}
}
};
</script>
// 父组件
<template>
<div>
<counter :value='value' @add='changeValue' @reduce='changeValue'/>
</div>
</template>
<script>
export default {
data () {
return {
value: 10
}
},
methods: {
changeValue (data) {
this.value = data
}
}
};
</script>
- 将加减执行的回到函数通过父组件传到子组件中实现改变数据
// 子组件
<template>
<div>
<van-button @click="add" type="default">加一</van-button>
<div>
{{countsVal}}
</div>
<van-button @click="reduce" type="default">减一</van-button>
</div>
</template>
<script>
export default {
props: {
value: Number,
add: Function,
reduce: Function
}
};
</script>
// 父组件
<template>
<div>
<counter :value='value' :add='add' :reduce='reduce'/>
</div>
</template>
<script>
export default {
data () {
return {
value: 10
}
},
methods: {
add (data) {
this.value++
},
reduce (data) {
this.value--
}
}
};
</script>
通过v-model
语法糖实现,父子组价的数据双绑
// 子组件
<template>
<div>
<van-button @click="changeVal(1)" type="default">加一</van-button>
<div>
{{countsVal}}
</div>
<van-button @click="changeVal(-1)" type="default">减一</van-button>
</div>
</template>
<script>
export default {
props: {
value: Number
},
data () {
return {
// props的初始化比data的初始化要靠前
countsVal: this.value
}
},
methods: {
changeVal (data) {
this.countsVal += parseInt(data)
this.$emit('input', this.countsVal)
}
}
}
</script>
// 父组件只需要通过v-model将数据传进去就好了
<template>
<div>
<counter v-model='counts'/>
</div>
</template>
<script>
import counter from './base/counter'
export default {
components: {
counter
},
data () {
return {
counts: 10
}
}
}
</script>