各组件之间的通信方法
🔺provide/inject(跨级组件通信)
允许一个祖先组件向其所有不论组件层次有多深的子孙后代注入一个依赖。 祖先组件中通过provide来提供变量,然后在子孙组件中通过inject来注入变量。
- provide:可以是一个对象或者是一个回调函数(返回一个对象)包含可以注入子孙组件的属性。
- inject:一个字符串数组或一个对象,对象的 key 是本地的绑定名。
-
value 是:
在可用的注入内容中搜索用的 key ,或一个对象,该对象的:
- from 属性 是在可用的注入内容中搜索用的 key。
- default 属性 是相当于一个默认值
<template>
<div>
<h1>父组件</h1>
<!-- <child-1-vue :val="info"></child-1-vue> -->
<child-1-vue></child-1-vue>
</div>
</template>
<script>
import child1Vue from "./components/child1.vue";
export default {
data() {
return {};
},
//作为一个对象
// provide: {
// info: {
// uname: "father",
// age: 20,
// },
// },
// 作为一个返回对象的函数
provide() {
return {
obj: {
uname: "father",
age: 19,
},
info: "789",
};
},
components: {
child1Vue,
},
created() {},
methods: {},
};
</script>
<style scoped></style>
<template>
<div>
<h1>child1,子组件</h1>
<p>props:</p>
<child-2-vue></child-2-vue>
</div>
</template>
<script>
import child2Vue from "./child2.vue";
export default {
data() {
return {};
},
props: {
val: {
type: String,
},
},
components: {
child2Vue,
},
created() {},
methods: {},
};
</script>
<style scoped></style>
<template>
<div>
<h1>child2,孙子组件</h1>
</div>
</template>
<script>
export default {
data() {
return {};
},
//接收一个字符串数组 ---》'{uname: "father",age: 20,}'
// inject: ["info"],
// 接收一个对象 ---》'{uname: "father",age: 19,}'
inject: {
obj: {
form: "obj",
},
info: {
from: "info",
},
},
created() {},
methods: {},
};
</script>
<style scoped></style>
使用场景:子孙组件和祖先组件之间的通信
🔺attrs/listeners
场景:多级组件嵌套需要传递数据时,且不需要处理数据的时候。
- attrs 里存放的是父组件中绑定的非 Props 属性。
- listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on=”$listeners” 传入内部组件
<template>
<div>
<p>祖先组件</p>
<child-com-1-vue :uname="uname" :age="age" @com1="com1"></child-com-1-vue>
</div>
</template>
<script>
import childCom1Vue from "./components/childCom1.vue";
export default {
data() {
return {
uname: "ls",
age: "20",
};
},
components: {
childCom1Vue,
},
created() {},
methods: {
com1() {
console.log("这是祖先组件的方法");
},
},
};
</script>
<style scoped></style>
<template>
<div>
<p>子组件1</p>
<child-com-2-vue v-bind="$attrs" v-on="$listeners"></child-com-2-vue>
</div>
</template>
<script>
import childCom2Vue from "./childCom2.vue";
export default {
data() {
return {};
},
components: {
childCom2Vue,
},
props: {
uname: {
type: String,
},
},
created() {
console.log(this.$attrs); //----{"age":"20"}
console.log(this.$listeners);
this.$listeners.com1(); //----“这是祖先组件的方法”
},
methods: {},
};
</script>
<style scoped></style>
<template>
<div>
<p>子组件2</p>
//---{"age":"20"}
</div>
</template>
<script>
export default {
data() {
return {};
},
created() {
console.log(this.$attrs); //---{"age":"20"}
this.$listeners.com1(); //----"这是祖先组件的方法"
},
methods: {},
};
</script>
<style scoped></style>
$parent,$children
- $children :可以获取当前组件的所有子组件,并且以数组的形式返回。
- $parent:可以获取当前组件的父组件,并返回当前父组件。
🔺eventBus(事件总线)
-
本质就是一个vue实例
-
创建实例 const eventBus = new Vue()
-
导出 export
-
在使用的组件中引入 import eventBus from “”
-
eventBus.$emit(‘事件名’,传递的数据),发布事件。
-
另一个组件中注册自定义事件 eventBus.$on(‘事件名’,(传递来的数据)=>{}),订阅事件。
设计模式:发布订阅模式:
一对多的依赖关系,
- 发布方为一,发布消息。
- 依赖方为多,订阅消息。
1.发布方进行事件发布,遍历存储起来的事件回调数组,再给每个回调传递参数,订阅方触发事件之后就可以拿到传递的参数。2.订阅方订阅事件,把事件和事件对应的函数(回调)存储起来,如果订阅多个相同的事件,那么可以把相同事件的回调都存到事件对应的数组里。($on做的只是把对应的事件以及回调存起来)。
//手写一个发布订阅模式
Class eventBus {
//定义一个接收事件的对象
clientList = {},
$on = function(event,callback){
//如果没有当前事件,那么就给当前事件名当做一个数组,里面存放事件回调
if(!this.clientList[event]){
this.clientList[event] = [callback]
}
//如果有当前事件,那么就给当前事件数组添加一个回调
this.clientList[event].push(callback)
},
$emit = function(event,val){
//把对象里每个属性拿出来放到一个数组中,遍历每个属性名(即对象名)
Object.keys(this.clientList).forEach(item =>{
//如果没有该事件,就跳出
if(!this.clientList[event]){
return false
}
//给每个属性里面的每个方法传递参数。
this.clientList[event].forEach(callback =>{
callback(val)
})
})
}
}
//new 一个事件总线实例
const event = new eventBus()
//订阅事件
event.$on('send',(val)=>{
console.log(val)
})
event.$on('send',(val)=>{
console.log(val)
})
//发布事件,并且给回调传参
event.$emit('send',1)
vuex
-
vuex就是基于vue的一个状态管理工具
-
它主要用于实现数据的共享,同时数据也是响应式的,因此它就方便了各个组件之间共享数据的操作,也有利于数据的维护的管理。
-
它有五个主要的状态:
- state 是用来存储和定义用来共享的数据的属性,可以用$store 或者是 辅助函数来拿到state的数据,因为辅助函数本质上会返回一个对象,可以把vuex中的数据映射过来,在使用的时候必须解构出来。
- mutations 是 用来修改state 数据的唯一来源,但是也可以直接修改state 中的数据,但是不建议,因为一旦数据出现错误会造成state中的数据混乱,它一般是用来处理同步流程,通过commit 提交给mutations 从而修改state 中的数据,如果用它处理异步流程,那么肯造成调试工具的不准确。
- actions 主要用来处理异步流程,通过dispatch 传递给 actions 在调用 mutations 来修改数据,一般在工作中,为了避免操作的繁琐,基本都把同步异步流程都放到actions中进行处理,而把数据的修改提交到mutations中。
- getters 主要把state中的数据新建派生处理,即根据state中的数据生成另一种数据。
- modules 主要是把vuex数据模块化,方便管理和维护,每个模块里都有对应模块的 state/mutations/actions/getters 属性,如果没有开启命名空间,模块中的 mutations/actions中的方法和全局中的并无差别,开启命名空间之后,使用各自模块的方法和数据都必须加上模块名,或者是根据createNamespacedHelper生成对应命名空间的辅助函数,它能拿到当前命名空间的所有辅助函数,从而实现对当前命名空间数据或方法的使用。
-
vuex的缺点就是 他其中的数据不支持持久化操作,当然我们可以通过添加本地存储的方式来实现手动持久化,或者是通过插件vuex-persistedstate 来实现自动的数据持久化操作,其中可以对指定模块进行数据持久化。
-
在日常的业务中,一般的用户信息以及用户唯一标识token都放到vuex中进行存储,以及一些多组件之间需要频繁传递的参数一般也放到vuex中进行存储。