Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
题目描述
我们在用vue开发项目时,经常会抽离出各种组件,这些组件之间,有时候也要通信交流来进行传值或响应事件等操作,可以说几种vue组件相互通信的方法吗?
考察点
- vue组件基础
- vuex基础
- 发布订阅模式理解
- 技术前瞻Vue3
解题思路
- 就是考察最基础的vue组件的使用,最普遍的方式是父子传值通信,如果出现兄弟层级或者层级加深的情况可以采用事件总线和vuex做状态存储也是用来通信的方案。
- 另外,Vue2可以使用EventBus做事件总线进行组件通信,而Vue3移除off 和 $once方法,所以推荐使用mitt.js。其原理都是发布订阅。
- Vue3可以用pinia代替vuex其使用更加简洁。
实现
父子传值
- 子组件在props中创建属性的类型与默认值,用以接收父组件传来的值。
- 父组件中注册子组件。
- 在子组件标签中添加其props中创建的属性。
- 把需要传给子组件的值赋给该属性,这样子组件便可获取到父组件的值。
- 同时,父组件可以在子组件中通过@绑定方法,然后子组件可以通过$emit向父组件发起响应。
子组件:
<template>
<div>
<p>msg:{{msg}}</p>
<button @click="handleEmit">emit</button>
</button>
</div>
</template>
<script>
export default {
name: "hello",
props:{
msg:{
type:String,
defalut:""
}
},
methods: {
handleEmit(){
this.$emit("ok","我是传值")
}
}
}
</script>
父组件:
<template>
<div>
<hello @ok="handleOk" :msg="msg" />
</div>
</template>
<script>
import Hello from "./hello"
export default {
components: {
Hello,
},
data(){
return {
msg:"我是消息"
}
},
methods: {
handleOk(value){
console.log(value)
}
}
}
</script>
事件总线
Vue2 EventBus
//在main.js中挂在在原型挂在一个全新的vue实例
Vue.prototype.$bus = new Vue()
//子组件中发出事件
this.$bus.$emit("myOnLoad");
//上级中执行监听
this.$bus.$on("myOnLoad",this.myEvent);
//上级中取消监听
this.$bus.$off("myOnLoad",this.myEvent);
Vue3 mitt.js
import mitt from "mitt";
const bus = {};
const emitter = mitt();
bus.$on = emitter.on;
bus.$off = emitter.off;
bus.$emit = emitter.emit;
export default bus;
状态维护
vuex
- store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const types = {
SET_USER: "SET_USER"
}
const state = {
user: null
};
const getters = {
user: state => state.user
};
const mutations = {
[types.SET_USER](state, user) {
if (user) state.user = user;
else state.user = null;
}
};
// 若存在异步须使用actions($store.dispatch),
// 若只是同步mutations也可($store.commit)
const actions = {
setUser: ({ commit }, user) => {
return new Promise((resolve,reject)=>{
commit(types.SET_USER, user);
resolve()
};
},
clearLogin: ({ commit }) => {
return new Promise((resolve,reject)=>{
commit(types.SET_USER, null);
resolve()
}
}
};
export default new Vuex.Store({
state,
getters,
mutations,
actions
})
- 使用
// 设置用户
this.$store
.dispatch('setUser',{usernmae:"jsmask"})
.then(()=>console.log('设置完成'));
// 清空用户
this.$store
.dispatch("clearLogin")
.then(()=>console.log('退出登录'));
可以在不同页面做出响应,共同维护这个状态,从而达到通信的效果。
pinia
详见官网Demo示例