什么是vue的组件通信
组件:是可以复用的vue实例
组件通信:每个组件是一个单独的整体,组件之间互相联系,就是组件通信
组件关系图
如图所示:A与B、A与C、B与D、C与E为父子关系,B与C为兄弟关系,A与D、A与E隔代亲,D与E为堂兄弟关系 ,可以将组件的关系归为两类:
- 父子关系
- 非父子关系(兄弟和隔代亲等…)
1、父子组件之间传递
1.1 父传子 props
1、数据存放在父组件中,在父组件中 给子组件添加一个属性,把值传给子组件
2、子组件中 使用props 进行接收 props:[]
// Parent.vue
<div id="app" style="border: 3px solid #000; margin: 20px">
我是父组件
<Son :title="title"></Son>
</div>
data() {
return {
title: '这是一个大标题',
}
},
// Son.vue
<template>
<div class="son" style="border: 3px solid #000; margin: 20px; padding: 10px">
我是son组件
<p>{{ title }}</p>
</div>
</template>
<script>
export default {
name: 'MyMson',
// 简单写法
// props: ['title'],
// 完整写法
props:{
title:{
type:String, // 类型
required: true, // 是否必填
default: 40, // 默认值
// 自定义校验
validator(value){}
}
}
}
</script>
<style></style>
1.2 子传父 $emit
子组件利用$emit通知父元素,进行修改更新
1、在子组件中 $emit 触发事件,给父组件发送消息通知
2、父组件监听事件,
3、提供处理函数,形参中获取参数
// 父组件 Parent.vue
<template>
<div id="app" style="border:3px solid #000;margin:20px">
我是父组件
<!-- 2、父组件需要对于子元素设置的事件进行监听 -->
<Son :title="title" @changeTitle="fatherFn"></Son>
</div>
</template>
<script>
import Son from './components/Son.vue'
export default {
// 父组件的数据
data(){
return {
title: '这是一个大标题',
}
},
methods:{
// 3、提供处理函数,处理逻辑
fatherFn(txt) {
console.log(txt)
this.fatherDate = txt
}
},
components:{ Son }
}
</script>
// 子组件 Son.vue
<template>
<div class="son" style="border:3px solid #000;margin:20px">
我是son组件 {{ title }}
<button @click="changeFn">修改标题</button>
</div>
</template>
<script>
export default {
props:{
title:String
},
methods:{
changeFn() {
// 1、通过$emit,向父组件发送数据
this.$emit('changeTitle','略略略~')
}
}
}
</script>
优化:
父子之间传参可以使用 v-model 传参
- 把需要给子组件传递的属性名修改为 value
- 子组件给父组件传递的事件名称修改为 input
注意点:
1、父级prop的数据更新,会向下流动,影响子组件。这个数据流动是单向的
2、子组件不可以修改父组件传的数据
2、非父子之间
2.1 eventBus 事件总线
可通过 EventBus 进⾏信息的发布与订阅。 (创建一个都能访问到的事件总线)
// EventBus.js
// 1、创建一个都能访问到的事件总线(空的vue实例)
import Vue from 'vue'
const Bus = new Vue()
export default Bus
// 2、在A组件(接收方),进行监听Bus事件(订阅消息)
Bus.$on('事件名',参数 => { ... })
// 3、B组件中, 触发 bus的事件
Bus.$emit('事件名','参数')
具体实现代码
组件A
<template>
<div class="baseA">
我是A组件(接收方)
{{data}}
</div>
</template>
<script>
import Bus from '../utils/EventBus'
export default {
data(){
return {
data:''
}
},
created() {
// 2、在A组件(接收方),进行监听Bus事件(订阅消息)
Bus.$on('sendMsg',msg => {
// console.log(msg)
this.data = msg
})
}
}
</script>
<style scoped>
.baseA {
width: 200px;
height: 150px;
padding: 10px;
margin-top: 10px;
border: 3px solid #000;
border-radius: 5px;
font-size: 20px;
}
</style>
组件B
<template>
<div class="baseA">
我是B组件(发布方)
<button @click="send">发布通知</button>
</div>
</template>
<script>
import Bus from '../utils/EventBus'
export default {
methods:{
send() {
// 3、在B组件(发送方)触发事件传递参数,帆布消息
Bus.$emit('sendMsg','我是B组件发过来的信息')
}
}
}
</script>
<style scoped>
.baseA {
width: 200px;
height: 150px;
padding: 10px;
margin-top: 10px;
border: 3px solid #000;
border-radius: 5px;
font-size: 20px;
}
</style>
2.2、provide 和 inject (跨层级共享数据)
简单来说就是 父组件 中通过 provide 来提供变量, 然后在 子组件 中通过 inject 来注入变量。
注意: 这对选项需要一起使用,不论子组件嵌套有多深, 只要调用了inject 那么就可以注入provide中的数据,而不局限于只能从当前父组件的props属性中数据
provide 选项应该是一个对象或返回一个对象的函数
inject 选项是一个字符串数组,或一个对象
// A.vue
provide() {
return {
// 简单数据类型(非响应式)
color: this.color,
// 复杂数据类型(响应式)推荐
userInfo: this.userInfo,
};
},
// GrandSon.vue
<template>
<div class="grandSon">
我是GrandSon
{{ color }} - {{ userInfo.name }} - {{ userInfo.age }}
</div>
</template>
<script>
export default {
inject: ["color", "userInfo"],
};
</script>
<style>
.grandSon {
border: 3px solid #000;
border-radius: 6px;
margin: 10px;
height: 100px;
}
</style>
2.3、 $attrs 和 $listeners
可以用来作为跨级组件之间的通信机制
父组件
<template>
<div>
<my-child1 :money="100" desc='你好哇' @test1="fn1" @test2="fn2"></my-child1>
</div>
</template>
子组件
<template>
<div class="my-child1">
<!-- $attrs => { "money": 100, "desc": "你好哇" } -->
<div>{{ $attrs }}</div>
<my-child2 v-bind="$attrs" v-on="$listeners"></my-child2>
</div>
</template>
<script>
import MyChild2 from './my-child2'
export default {
created() {
console.log(this.$listeners)
},
components: {
MyChild2,
},
}
</script>
孙组件
<template>
<div>
我是child2 - {{ money }} - {{ desc }}
<button @click="clickFn">按钮</button>
</div>
</template>
<script>
export default {
props: ['money', 'desc'],
methods: {
clickFn () {
this.$emit('test1', '嘎嘎')
this.$emit('test2', '嘿嘿')
}
}
}
</script>
2.4、vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
如果需要构建一个中大型单页应用,可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。
vuex的模块
state: 存放数据
mutations: 存放操作数据的方法
actions: 存放一些异步操作 (也可以进行一些同步处理) 注意: actions 是不能直接修改 state 数据的, 需要提交 mutation
getters: 存放基于 state 计算出来的一些值 (计算属性)
modules: 分模块, 项目大了, 也推荐分模块管理 (同模块的 vuex 操作, 就会在一起)
the end…