vue 组件之间的通信


目录
  • vue 组件之间通信的六种方式
    • 1、props 和 $emit(子 触发 父)、ref(父 调用 子)
    • 2、Event Bus(emit)
      • 疑问点:为什么不能使用 this.on ,而要重新 new 一个空的 vue 实例?
    • 3、provide 和 inject
    • 4、$parent 和 $children
    • 5、$attrs 和 $listeners
    • 6、Vuex

vue 组件之间通信的六种方式

1、props 和 $emit(子 触发 父)、ref(父 调用 子)
  • 父组件 给 子组件 数据传递,一般使用 props 关键字。
  • 子组件 给 父组件 传递数据,一般使用 $emit 方式触发 父组件 的事件;因为 子组件 是 不能直接修改 props 中的值(即 父组件 传递的值)的,若需要修改,则要通过触发 父组件 的事件,告知父组件进行修改。
  • 父组件 直接调用 子组件 的方法,可用 $refs 获取到子组件的实例,从而调用其方法。

示例代码如下:

// Parent.vue



// Child.vue



2、Event Bus(\(on、\)emit)
  • Event Bus(事件总线)方式主要用于无父子关系的组件之间传值,比如兄弟组件之间
  • 在 组件A 中使用 $on 注册监听事件,在 组件B 中使用 $emit 触发事件

示例代码如下:

// 新建一个vue实例,作为事件总线;可将其注册到全局或者vue的propotype上
vue.propotype.eventBus = new Vue();
// CompA.vue



// CompB.vue



疑问点:为什么不能使用 this.\(emit 和 this.\)on ,而要重新 new 一个空的 vue 实例?
3、provide 和 inject
  • provide 和 inject 方式通常用于祖孙组件之间的通信,主要用于祖先组件向子组件传值
  • provide 用于在 祖先组件 中定义可向子组件注入的属性或方法
  • inject 用于在 子组件 中注入属性和方法等依赖

示例代码:

// CompA.vue



// CompB.vue



4、$parent 和 $children
  • $parent 和 $children 用于有 直接父子关系 的 组件 之间的通信
  • $parent 用于 获取组件的父组件实例
  • $parent 用于 获取组件的子组件实例
5、$attrs 和 $listeners
  • $attrs 和 $listeners 主要用于 获取 父组件 的属性和方法
  • $attrs 用于获取父组件中 没有在子组件的props中接收的属性
  • $listeners 用于获取父组件中的自定义事件
6、Vuex

Vuex 类似于一个仓库,可存放一些数据供全局调用,但是刷新页面就会消失,若需解决此问题,可选择将数据存储到 Vuex 的同时,将其存放到 sessionStorage 或者 localStorage 中即可。

Vuex 中包括 state、mutations、actions、getters、modules 几个部分。其中

  • state:定义变量
  • getters:获取state中变量的值
  • mutations:修改 state 中的值;使用 commit 触发;只能进行同步操作
  • actions:进行各种操作,可通过 dispatch 触发;可以进行异步操作
  • modules:项目较大时,可对变量的管理进行拆分,拆分成多个js文件,每个js文件作为单个的module,然后统一注册到 index.js 中,供全局调用

示例代码:

// module.js

const state = {
    modelCreateDataJsonStr: "",
    modelSelectDataJsonStr: "",
    modelClassDataJsonStr: ""
};
const getters = {
    getModelCreateDataJsonStr: state => {
        return state.modelCreateDataJsonStr;
    },
    getModelSelectDataJsonStr: state => {
        return state.modelSelectDataJsonStr;
    },
    getModelClassDataJsonStr: state => {
        return state.modelClassDataJsonStr;
    }
};
const mutations = {
    SET_MODEL_CREATE_DATA_JSON_STR(state, modelCreateDataJsonStr) {
        state.modelCreateDataJsonStr = modelCreateDataJsonStr;
    },
    SET_MODEL_SELECT_DATA_JSON_STR(state, modelSelectDataJsonStr) {
        state.modelSelectDataJsonStr = modelSelectDataJsonStr;
    },
    SET_MODEL_CLASS_DATA_JSON_STR(state, modelClassDataJsonStr) {
        state.modelClassDataJsonStr = modelClassDataJsonStr;
    }
};
const actions = {
    setModelCreateDataJsonStr({commit}, modelCreateDataJsonStr) {
        commit("SET_MODEL_CREATE_DATA_JSON_STR", modelCreateDataJsonStr);
    },
    setModelSelectDataJsonStr({commit}, modelSelectDataJsonStr) {
        commit("SET_MODEL_SELECT_DATA_JSON_STR", modelSelectDataJsonStr);
    },
    setModelClassDataJsonStr({commit}, modelClassDataJsonStr) {
        commit("SET_MODEL_CLASS_DATA_JSON_STR", modelClassDataJsonStr);
    }
};

// 暴露仓库
export { state, getters, mutations, actions };
// index.js

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

/**
 * 批量导入module下的所有模块
 * 如果module下面有自己新建的文件夹  文件夹里面的JS文件不能用index命名  容易冲突
 */
const path = require('path');
const files = require.context('./module', true, /\.js$/);
const modules = {};
files.keys().forEach(key => {
    const name = path.basename(key, '.js'); // 返回key的最后一部分
    modules[name] = files(key).default || files(key);
});

Vue.use(Vuex);
const store = new Vuex.Store({
    modules: modules,
});
export default store;
vue