1.组件间通信的方式
- 父子组件:
- 使用
props和emit(),通过事件通信 - 通过
this.$refs或者$parent和$children取得父子元素方式通信 - 子组件通过设置插槽
<slot name=''></slot>实现父传子通信
- 使用
- 爷孙组件:
- 使用两次
props和emit(),通过爷爷爸爸通信,爸爸儿子通信实现爷孙通信 $attr和$listeners
- 使用两次
- 任意组件:
- 使用
eventBus = new Vue()来通信,eventBus.$on和eventBus.$emit是主要API - 使用
Vuex通信
- 使用
2. 父子通信
2.1props和emit()
2.1.1 父传子:父亲给儿子绑定属性,儿子通过props接收
//父组件
<Child :name="father" :f_data="message"/>
//子组件
props:['name','f_data']
//子组件2
props:{
name:{
type:String,
default: 'father',
},
f_data:{
type: String|Number,
validator(){}
}
}
2.1.2 子传父:子组件通过emit()调用父组件在子组件上v-on绑定的方法,以向方法传参的方式通信
//父组件
<Child v-on:handle='changeMsg'></Child>
//子组件 向父组件传递value数据
<button @click="$emit('handle',value)"></button>
2.2 this.$refs或者$parent和$children,都是获取父亲或儿子的vue实例
//子组件
<template>
<button>click me </button>
</template>
<script>
export default {
data(){
return{
sonMessage:'儿子的信息'
},
mounted(){
console.log(this.$parent.$el.innerHTML);
//<div><button>click me </button></div> <p>爸爸组件</p>
}
}
</script>
//父组件
<template>
<div>
<child ref='childRef'>click me </child>
<p>爸爸组件</p>
</div>
</template>
<script>
export default {
data(){
return{
fatherMessage:'父亲的信息'
}
}
},
mounted(){
console.log(this.$refs.childRef.sonMessage); //儿子的信息
console.log(this.$children[0].sonMessage); //儿子的信息
}
</script>
2.3 <slot></slot>
父组件
<div>
<Child>这是默认内容
<template v-slot:name>
张三
</template>
<Child>
</div>
子组件
<div>
<slot></slot> <!--这是默认内容-->
<slot name='title'></slot> <!--张三-->
</div>
3. 爷孙通信
3.1 使用两次props和emit()
爷爷组件
<template>
<parent name='zhanshan' @onParentClick="sendMessage" ></parent>
</template>
<script>
import Vue from 'vue'
import Parent from './parent.vue'
Vue.component('parent', Parent);
export default {
methods: {
sendMessage(sonMsg){
console.log(sonMsg) //来自孙子的信息
}
}
}
</script>
父亲组件
<template>
<child :name='name' @onChildClick="$emit('onParentClick',arguments[0])" ></child>
</template>
<script>
import Vue from 'vue'
import Child from './child'
Vue.component('child', Child);
export default {
props:['name']
}
</script>
孙子组件
<template>
<button @click="$emit('onChildClick','来自孙子的信息')" >click me </button>
</template>
<script>
export default {
props: ['name'] //'zhangshan'
}
</script>
爷爷通过向父亲设置name属性,父亲接收再设置,从而儿子接收到爷爷的信息。而儿子通过emit()调用爷爷传给父亲的方法,向爷爷传递参数完成通信
3.2 使用$attr和$listeners简化上述3.1步骤
使用$attr的主要代码
// 爷爷
<Parent name="zhangshan"/>
// 父亲
<Child v-bind="$attrs"/>
// 孙子 props接收
<div>{{name}}</div>
props:['name']
// 孙子 props 不接收
<div>{{$attrs.name}}</div>
使用$listeners的主要代码
//爷爷
<parent @onChildClick="sendMessage" ></parent>
methods: {
sendMessage(sonMsg){
console.log(sonMsg) //来自孙子的信息
}
//父亲
<child v-on="$listeners" ></child>
//孙子
<button @click="$emit('onChildClick','来自孙子的信息')" >click me </button>
4. 任意组件通信
4.1 声明一个全局 Vue 实例变量 EventBus ,把需要通信的数据,上传到这个变量上,能实现各个组件的通信。相当于组件订阅eventBus,某个组件向eventBus传递信息,则eventBus向其他所有订阅它的组件发布该信息
兄弟通信示例
//父组件
data(){
return{
eventBus:new Vue()
}
},
provide(){ //提供事件中心,使得其所有子孙组件可以使用到eventBus,或者作为js用import引入
return{
eventBus:this.eventBus
}
},
mounted(){
this.eventBus.$on('click',(a_message)=>{ //监听eventBus的信息
console.log(a_message); //childB的信息
})
//ChildA组件
<template>
<div>
<button @click='onClickFun'>childA按钮</button>
</div>
</template>
<script>
export default {
inject:['eventBus'], //接收事件中心
data(){
return{
a_message:'childB的信息'
}
},
methods: {
onClickFun(){//点击按钮,向eventBus发送信息 a_message
this.eventBus.$emit('click',this.a_message)
}
}
</script>
//ChildB组件
inject:['eventBus'], //接收事件中心
mounted(){
this.eventBus.$on('click',(a_message)=>{ //监听eventBus的信息
console.log(a_message); //childB的信息
})
4.2 Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
访问state数据
//store.js
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
//自定义共享状态
state: {
isMsg: true
}
});
//main.js
import store from "./store";
new Vue({
store, //将store挂载到Vue实例中
render: h => h(App)
}).$mount("#app");
<!--App.vue-->
<div id='app'>{{$store.state.isMsg}}</div> <!--true-->
通过mutation修改数据
<!--App.vue-->
<button @click = 'onClick'>修改VueX中的isMsg</button>
methods:{
onClick(){
this.$store.commit('onChangeMsg',false) //第一个参数为mutation名字
}
},
//store.js
export default new Vuex.Store({
state: {
isMsg: true
},
mutations: { //修改数据唯一途径,专注于修改数据好多年
onChangeMsg(state, data) {
state.isMsg = data;
console.log('修改了data');
}
},
通过actions 发送异步请求
//app.vue
<button @click='onDispatch'>通过actions发送异步请求</button>
<span>OuterData:{{$store.state.outerData}}</span> //异步请求的数据
methods:{
onDispatch(){
this.$store.dispatch("getOuterData")
}
//store.js
export default new Vuex.Store({
state: {
outerData: '' //将异步请求获取的数据存到state中,下次请求直接从state中拿
},
mutations: {
onGetOuterData(state, data) {
state.outerData = data;
}
},
actions: {
getOuterData(state) {
axios({
url: 'xxxx', //请求数据的地址
headers: {}
}).then((res) => {
state.commit('onGetOuterData',res.data)
})
}
},
});
总结:根据官方流程图,VueX修改数据的顺序为,通过Dispatch方法使用Actions请求异步数据,通过Commit方法提交到Mutations中,再通过commit方法将数据添加或修改到State中