项目中关于组件的使用经常会碰到这种情况:父子组件传和方法调用、兄弟组件的传值和方法调用、多个独立组件的数据共享和方法调用,例如:a、b
组件的的数据共享,该数据是由c
传出的,通过a、b
组件修改共享参数,调用c
方法实现a、b
组件的数据更新。本文总结了上述的几种情况并分别讲解。
兄弟组件的传值和方法调用
框架:vue2
通过组件ref
调用组件内的方法
父组件
<template> <div> <MyA @save="save"></MyA> <MyB ref="listNode"></MyB> </div> </template> <--! js部分 --> methods: { save() { // 通过ref调用兄弟组件的方法 this.$refs.listNode.submit(); } }
组件一
// MyA <el-button type="parimary" size="mini" @click="sure">确定</el-button> // js methods: { sure() { // 保存点击,数据通过$emit传出 this.$emit('save') }
组件二
// MyB <el-button type="parimary" size="mini" @click="submit">提交</el-button> // js methods: { submit() { console.log('方法被触发了') } }
A
组件通过emit
将方法回传,父组件触发A
组件回传的事件,在父组件中通过ref
在调用B
组件内的事件。
多个独立组件的数据共享和方法调用
多个组件内的方法和数据互相驱动:eventBus
框架:vue2
新建一个eventBus.js
,定义事件全局事件总线。
// eventBus.js import Vue from 'vue' export default new Vue(); // 该文件就两行
引入到main
文件,挂载到vue
原型上
// main.js import Vue from 'vue' import eventBus from '@/utils/eventBus.js' // ..... Vue.prototype.$bus = eventBus // 挂载到原型 // ...
然后就可以在页面中使用了,使用的页面需要引入eventBus.js
// A组件 import bus from '@/utils/eventBus.js' methods: { // 分页 handleSizeChange(val) { // 广播方法 bus.$emit('sizeChange',{page : val }) }, }
// B组件 import bus from '@/utils/eventBus.js' created() { // $off解绑 bus.$off( 'sizeChange' ); // 使用前先解绑,否则在某些情况下会触发两次 // $on监听触发 bus.$on('sizeChange', (val) => { // 事件内的操作.... this.getTable(val); }) }, methods: { getTable(val) { // 通过bus触发 console.log(val); // { page: val } }, }
需要注意的是,
eventBus
的$on
事件需要在created
等生命周期中使用,如果写在methods
中使不会自动触发的。使用$on
事件的时候需要先解绑,否则页面刷新后监听事件没有解绑,后续再次广播事件会触发两次。解绑可以在beforeDestory
中操作也可以$off 后接 $on
解绑后监听
eventBus
相当于一个全局事件池,向全局事件池中添加和传入事件,事件池的事件可以作用于全局。
多个组件的数据共享以及数据修改:vuex
框架:vue3
vuex
中可以存储全局数据以及事件,我们可以在任何页面访问vuex
中的事件和方法,随着项目持续维护,我们不可能直接在store
中的index
中直接添加数据和方法,因此vuex
提供了module
功能,可以让我们分别管理自己独立的module
模块。
官网上是这么说的:
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。
npm install vuex@next --save • 1
// sotre -> my_module const my_module = { state: () => ({ my_count : 0, my_info : { id : 1, name : '我的模块' } }), mutations: { countChange(state,val) { state.my_count += val } }, actions: { // actions不直接修改数据 // context为store中的上下文,通过commit驱动mutations的方法来实现数据修改 countTen(context,num){ setTimeout(()=>{ context.commit('countChange',num.num) },500) } }, getters: { getMyName (state) { return `这是${state.my_info.name}` }, getMyCount (state) { return `我的总数:${state.my_count}` } } } export default my_module;
// store -> index.js import { createStore } from "vuex"; import my_module from "./my_module"; // 创建store实例 const store = createStore({ // 将my_module 挂载到modules中 modules: { my_module } }) export default store;
// main.js import { createApp } from 'vue' import './style.css' import App from './App.vue' import store from './store/index' // 导入vuex createApp(App) .use(store) // 挂载vuex .mount('#app')
// 页面中使用 <template> <div> <div>vuex——module</div> <div>store中的值:{{ store.getters.getMyName }}</div> <div>store中的值:{{ store.getters.getMyCount }}</div> <button @click="addMyNum">count++</button> <button @click="numMyTen">每次加10</button> </div> </template> <script setup> import { ref,computed} from "vue" import { useStore} from 'vuex' // vue3中通过useStore使用store const store = useStore(); // vuex-module const addMyNum = () => { store.commit('countChange',1) } const numMyTen = () => { store.dispatch('countTen',{num:10}) } </script>
vuex一般用来做全局状态管理,并不建议向vuex中存储非全局的事件和方法,如果所有的跨组件事件和方法都向vuex中存储,随着项目的持续维护,store中的数据就会越来越多,会导致vuex维护成本变高。
vue3-setup组件传值 (👈点击直达)
微信小程序组件封装传值以及问题点规避 (👈点击直达)
vue3 语法糖setup 兄弟组件传值(👈点击直达)
微信小程序wxs封装使用以及公共js组件封装 (👈点击直达)
微信小程序的全局弹窗以及全局实例(👈点击直达)
如果觉得这篇文章对你有帮助,欢迎点赞👍、收藏💖、转发✨哦~