面题系列:vue组件间通信

168 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

题目描述

我们在用vue开发项目时,经常会抽离出各种组件,这些组件之间,有时候也要通信交流来进行传值或响应事件等操作,可以说几种vue组件相互通信的方法吗?

考察点

  1. vue组件基础
  2. vuex基础
  3. 发布订阅模式理解
  4. 技术前瞻Vue3

解题思路

  1. 就是考察最基础的vue组件的使用,最普遍的方式是父子传值通信,如果出现兄弟层级或者层级加深的情况可以采用事件总线和vuex做状态存储也是用来通信的方案。
  2. 另外,Vue2可以使用EventBus做事件总线进行组件通信,而Vue3移除onon、off 和 $once方法,所以推荐使用mitt.js。其原理都是发布订阅。
  3. Vue3可以用pinia代替vuex其使用更加简洁。

实现

父子传值

  1. 子组件在props中创建属性的类型与默认值,用以接收父组件传来的值。
  2. 父组件中注册子组件。
  3. 在子组件标签中添加其props中创建的属性。
  4. 把需要传给子组件的值赋给该属性,这样子组件便可获取到父组件的值。
  5. 同时,父组件可以在子组件中通过@绑定方法,然后子组件可以通过$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

  1. 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
})
  1. 使用
// 设置用户
this.$store
    .dispatch('setUser',{usernmae:"jsmask"})
    .then(()=>console.log('设置完成'));

// 清空用户
this.$store
    .dispatch("clearLogin")
    .then(()=>console.log('退出登录'));

可以在不同页面做出响应,共同维护这个状态,从而达到通信的效果。

pinia

详见官网Demo示例