为什么要进行组件通信?
组件是一个聚合体,将来项目要合并,那么必然各个组件之间需要建立联系,这个联系就是数据通信
vue组件通信
- 父子组件通信: props
- 子父组件通信: 自定义事件
- 非父子组件通信: ref 、 bus
- 多组件状态共享: vuex
- 数据预载: vue-router
父子通信
父组件将自己的数据同 v-bind 绑定在 子组件身上
子组件通过 props属性接收
老爸发红包给儿子(父组件传递数据给子组件)
<body>
<div id="app">
<Father></Father>
</div>
<template id="father">
<div>
<!-- 使用单项数据绑定将一个数据绑定给一个自定义的属性 -->
<Son :aa = "money" />
</div>
</template>
<template id="son">
<div>
<p>老爸给了我 {{ aa }} 块 </p>
<p> {{ aa + 20 }} </p>
</div>
</template>
</body>
<script src="../../../lib/vue.js"></script>
<script>
Vue.component('Father',{
template: '#father',
data () {
return {
money: 4000
}
}
})
Vue.component('Son',{
template: '#son',
/* 子组件通过props选项来接收属性,接收到的属性可以像全局变量一样在组件的模板中使用 */
// props: ['aa']
/* 属性验证 - js是弱类型语言*/
props: {
// 'aa': Number // String Boolean Object Array
'aa': {
validator ( val ) {
return val > 3000
}
}
/* vue3.0使用ts,ts是强类型 */
}
})
new Vue({
el: '#app'
})
</script>
子父通信
是通过自定义事件
事件的发布
通过绑定元素身上实现
事件的订阅
通过this.$emit触发 // html
儿子给老爸发红包(子组件给父组件传数据)
<body>
<div id="app">
<Father></Father>
</div>
<template id="father">
<div>
<p> 儿子给我发了 {{ xiaojinku }} 的红包 </p>
<!-- 自定义事件 -->
<Son @hongbao = "get"/>
</div>
</template>
<template id="son">
<div>
<button @click = "give"> 发红包 </button>
</div>
</template>
</body>
<script src="../../../lib/vue.js"></script>
<script>
Vue.component('Father',{
template: '#father',
data () {
return {
xiaojinku: 0
}
},
methods: {
get ( val ) {
this.xiaojinku = val
}
}
})
Vue.component('Son',{
template: '#son',
data () {
return {
hongbao: 2000
}
},
methods: {
give () {
this.$emit('hongbao',this.hongbao)
}
}
})
new Vue({
el: '#app'
})
</script>
非父子通信
兄弟通信
实现方法:ref 链
bus总线
ref链
<body>
<div id="app">
<Father></Father>
</div>
<template id="father">
<div>
<h3> father组件 </h3>
<hr>
<!-- 使用自定义属性形式将一个方法传递给子组件 -->
<Girl :kick = "getSon"></Girl>
<hr>
<Son ref = "son"></Son>
</div>
</template>
<template id="son">
<div>
<h3> son组件 </h3>
<img v-if = "flag" src="https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3872048339,4140466773&fm=26&gp=0.jpg" alt="">
<img v-else src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=2438534582,3797477605&fm=26&gp=0.jpg" alt="">
</div>
</template>
<template id="girl">
<div>
<h3> girl组件 </h3>
<button @click = "hit"> 揍弟弟 </button>
</div>
</template>
</body>
<script src="../../../lib/vue.js"></script>
<script>
Vue.component('Father',{
template: '#father',
methods: {
getSon () {
console.log( this )
this.$refs.son.changeFlag()
}
}
})
Vue.component('Son',{
template: '#son',
/* 组件是独立的,自己的数据自己改 */
data () {
return {
flag: true
}
},
methods: {
changeFlag () {
this.flag = !this.flag
}
}
})
Vue.component('Girl',{
template: '#girl',
props: ['kick'],
methods: {
hit () {
this.kick()
}
}
})
new Vue({
el: '#app'
})
</script>
bus总线
<body>
<div id="app">
<Father></Father>
</div>
<template id="father">
<div>
<h3> father组件 </h3>
<hr>
<!-- 使用自定义属性形式将一个方法传递给子组件 -->
<Girl></Girl>
<hr>
<Son></Son>
</div>
</template>
<template id="son">
<div>
<h3> son组件 </h3>
<img v-if = "flag" src="https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3872048339,4140466773&fm=26&gp=0.jpg" alt="">
<img v-else src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=2438534582,3797477605&fm=26&gp=0.jpg" alt="">
</div>
</template>
<template id="girl">
<div>
<h3> girl组件 </h3>
<button @click = "hit"> 揍弟弟 </button>
</div>
</template>
</body>
<script src="../../../lib/vue.js"></script>
<script>
/* 定义了实例bus - bus上有 $on $emit */
var bus = new Vue()
Vue.component('Father',{
template: '#father',
})
Vue.component('Son',{
template: '#son',
/* 组件是独立的,自己的数据自己改 */
data () {
return {
flag: true
}
},
mounted () {
/* mounted表示挂载结束,也就是我们能看到界面了,也就是事情做完了 */
/* 这个函数会自动执行 */
var _this = this
/* 通过bus绑定了自定义事件 */
bus.$on('ku',function () {
_this.flag = !_this.flag
})
}
})
Vue.component('Girl',{
template: '#girl',
methods: {
hit () {
bus.$emit('ku')
}
}
})
new Vue({
el: '#app'
})
</script>