关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

再也不用担心组件跨层级的数据共享和方法驱动了

发布时间:2023-06-30 12:01:00

项目中关于组件的使用经常会碰到这种情况:父子组件传和方法调用、兄弟组件的传值和方法调用、多个独立组件的数据共享和方法调用,例如:a、b组件的的数据共享,该数据是由c传出的,通过a、b组件修改共享参数,调用c方法实现a、b组件的数据更新。本文总结了上述的几种情况并分别讲解。

兄弟组件的传值和方法调用

框架:vue2

通过组件ref调用组件内的方法

父组件

     methods: {  save() {  // 通过ref调用兄弟组件的方法  this.$refs.listNode.submit();  } }

   

组件一

// MyA 确定// js methods: {  sure() {  // 保存点击,数据通过$emit传出  this.$emit('save')  }

   

组件二

// MyB 提交// 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')

     

// 页面中使用   vuex——module store中的值:{ { store.getters.getMyName }} store中的值:{ { store.getters.getMyCount }} count++ 每次加10 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}) } " _ue_custom_node_="true">

   

vuex一般用来做全局状态管理,并不建议向vuex中存储非全局的事件和方法,如果所有的跨组件事件和方法都向vuex中存储,随着项目的持续维护,store中的数据就会越来越多,会导致vuex维护成本变高。


vue3-setup组件传值 (点击直达)

微信小程序组件封装传值以及问题点规避 (点击直达)

vue3 语法糖setup 兄弟组件传值(点击直达)

微信小程序wxs封装使用以及公共js组件封装 (点击直达)

微信小程序的全局弹窗以及全局实例(点击直达)

如果觉得这篇文章对你有帮助,欢迎点赞、收藏、转发哦~


/template/Home/leiyu/PC/Static