首页 > 其他分享 >再也不用担心组件跨层级的数据共享和方法驱动了

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

时间:2023-06-11 18:12:49浏览次数:43  
标签:层级 数据共享 js module 组件 import vuex store

@

目录

项目中关于组件的使用经常会碰到这种情况:父子组件传和方法调用、兄弟组件的传值和方法调用、多个独立组件的数据共享和方法调用,例如: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
// 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组件传值

标签:层级,数据共享,js,module,组件,import,vuex,store
From: https://www.cnblogs.com/wang-fan-w/p/17473301.html

相关文章

  • React - 06 初步尝试封装组件
    1.封装dialog组件调用2.函数组件是静态组件/*函数组件是“静态组件”第一次渲染组件,把函数执行+产生一个私有的上下文:EC(V)+把解析出来的props「含children」传递进来「但是被冻结了」+对函数返回的JSX元素「virtualDOM」进行渲染当我们点击按钮的......
  • Vue 中通过事件总线方式组件间传递数据及调用 Vue脚手架中的axios数据调用方式获取git
    1:看界面效果2:代码结构3:代码内容3.1:引入第三方css样式表:bootstrap.css/*!*Bootstrapv3.3.5(http://getbootstrap.com)*Copyright2011-2015Twitter,Inc.*LicensedunderMIT(https://github.com/twbs/bootstrap/blob/master/LICENSE)*//*!normalize.cssv3.0.3|......
  • 分布式流处理组件-理论篇:Broker
    ......
  • 前端基于 radio 增强单选框组件
    前端基于radio增强单选框组件, 下载完整代码请访问uni-app插件市场地址:https://ext.dcloud.net.cn/plugin?id=12977效果图如下:    #####使用方法```使用方法<!--radioData:单选数据curIndex:当前选择序列@change:单选事件--><ccRadioView:radioData="i......
  • 能让你生活更容易的6个AI组件(除了ChatGPT)
    目录1、Tom:AI驱动的演示构建者2、QuillBot:一个AI工具可以增强你的写作能力3、Descript:更容易的视频与音频的编辑4、BHuman:上规模的AI驱动的个性化视频5、CleanupPictures6、NotionAI:写作更快并且增加你的创造力但是,那不是全部。除了生成文本,NotionAI也是一个强大的编辑器。他......
  • Springboot项目展示层级结构后端工具类
    publicclassMenuHelper{/***使用递归方法建菜单*@paramsysMenuList*@return*/publicstaticList<SysMenu>buildTree(List<SysMenu>sysMenuList){//存放最终数据List<SysMenu>trees=newArrayList<......
  • Vue进阶(幺贰零):父组件获取子组件验证结果
    (文章目录)一、前言在开发Vue项目过程中,代码复用之自定义组件是常做事情。当子组件为form表单的时候,父组件需要获取子组件(表单)的验证结果。尽管有prop和事件,但是有时仍然需要在JavaScript中直接访问子组件。为此可以使用ref为子组件指定一个引用ID。ref被用来给元素或子......
  • React - 04 函数组件的底层渲染机制
    1.函数组件创建:在SRC目录中,创建一个xxx.jsx的文件,就是要创建一个组件;我们在此文件中,创建一个函数,让函数返回JSX视图「或者JSX元素、virtualDOM虚拟DOM对象」;这就是创建了一个“函数组件”!!调用:基于ES6Module规范,导入创建的组件「可以忽略.jsx后缀名」,然后像写标签一样调用这个组......
  • 前端vue简单好用的上拉加载下拉刷新组件,支持列表分页 本地分页
    前端vue简单好用的上拉加载下拉刷新组件,支持列表分页本地分页, 下载完整代码请访问uni-app插件市场地址: https://ext.dcloud.net.cn/plugin?id=12942效果图如下:    ####使用方法```使用方法<!--pullDown:下拉刷新back-top:回到顶部 --><ccPullScro......
  • Python使用tkinter的Treeview组件实现表格功能
    fromtkinterimportTk,Scrollbar,Framefromtkinter.ttkimportTreeview#创建tkinter应用程序窗口root=Tk()#设置窗口大小和位置root.geometry('500x300+400+300')#不允许改变窗口大小root.resizable(False,False)#设置窗口标题root.title('通信录管理系统')#使......