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
我是Parent组件
// Child.vue
我是Child组件
父组件传的值:{{this.parentValue}}
2、Event Bus(\(on、\)emit)
- Event Bus(事件总线)方式主要用于无父子关系的组件之间传值,比如兄弟组件之间
- 在 组件A 中使用 $on 注册监听事件,在 组件B 中使用 $emit 触发事件
示例代码如下:
// 新建一个vue实例,作为事件总线;可将其注册到全局或者vue的propotype上
vue.propotype.eventBus = new Vue();
// CompA.vue
我是CompA组件
value的值:{{ value }}
// CompB.vue
我是CompB组件
疑问点:为什么不能使用 this.\(emit 和 this.\)on ,而要重新 new 一个空的 vue 实例?
3、provide 和 inject
- provide 和 inject 方式通常用于祖孙组件之间的通信,主要用于祖先组件向子组件传值
- provide 用于在 祖先组件 中定义可向子组件注入的属性或方法
- inject 用于在 子组件 中注入属性和方法等依赖
示例代码:
// CompA.vue
我是CompA组件
value的值:{{ value }}
// CompB.vue
我是CompB组件
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;