首页 > 其他分享 >使用vuex实现任意组件间通信

使用vuex实现任意组件间通信

时间:2023-07-19 17:11:39浏览次数:40  
标签:value 间通信 state 组件 commit vuex store

title: 使用vuex实现任意组件间通信
date: 2023-07-19 15:51:54
tags:
- vue
categories:
- 工程
- 前端
top:

使用vuex实现任意组件间通信

学习vue的第五天,学到了用插件vuex来实现vue任意组件之间的通信。

以下是个人理解,如有错误请指正。

vuex描述

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

vuex实现了共享数据的功能,当一个组件想要获取数据时直接向vuex发送请求即可,当一个组件想修改vuex中的数据时可以通过显式调用dispatch和commit来对vuex管理的状态进行修改。

image-20230719155810712

这个图片vuex官网贴的一张vuex内部逻辑图片,左边绿色的是组件

  • 当一个组件想要修改vuex管理的数据(state)时,可以 通过调用dispatch方法,需要传递两个参数,第一个是string类型的传入的是Actions中的方法名,第二个是要向方法中传递的参数value。
  • 当Actions接收到一个dispatch时,会向自身去寻找是否有第一个参数的方法名,如果没有就提示错误,找到之后就将第二个参数传入该方法。在Actions中的方法一般有两个参数,第一个是context也就是将vuex本身的一些方法包括(commit、state、dispatch······)这些传给方法,方便在逻辑处理之后进行下一步操作,第二个参数就是value,也就是用户传入的数据,如果是单数据就可以直接用,多数据的话可以传对象。
  • 在Actions中处理逻辑之后一方面可以再次调用dispatch进行下一个阶段的逻辑处理,另一个是直接调用commit将操作发送到Mutations中。当然组件也可以直接通过commit方法向Mutations传。这里有两个参数,第一个是Mutations中的方法名(string),第二个是要操作的数据。
  • Mutations中的方法在检测到有调用时会收到两个参数,第一个是state,也就是vuex储存的数据,第二个是组件要传入的数据。这时就可以进行操作将state中的数据进行更新。
  • 当state中的数据更新后,用到数据的组件也会进行重新的渲染。

由于整个流程中只有Mutations中的方法在真正的操作state中的数据,所以vue开发者工具的监测只针对Mutations。在Actions中可以进行一些复杂的逻辑操作,也可以向其他的服务器发送信息等来验证自己的数据是否合理。

vuex安装配置

上面整理完vuex的工作流程,这里是vuex的安装。

通过npm install vuex@3进行安装即可,这里有一个点是如果使用的是vue2.0的版本,那么vuex就应该下载3.0版本,因为vuex的4.0版本是为vue3.0服务的,所以在npm安装的时候要注意一下选择版本号。

安装完成之后就可以开始配置了。

因为vuex是一个全局的状态管理,有点类似全局事件总线,所以应该将vuex安装在vue实例对象身上,这样任意组件都可以访问到vuex。vuex在vue的配置中叫store,在创建vue实例的时候将其配置到对象中即可。

image-20230719162032157

可以看到这里有一个store是通过外部引入的,这个就是vuex的配置文件,在src下创建一个store文件夹,文件夹里创建一个index.js文件用来写vuex的配置。

插件的安装需要用到Vue.use(),方法,所以在这个文件中也要引入vue。引入vuex之后,可以开始配置了。

上面图中看到vuex的store中有三个主要的内容也可以说是配置对象,就是actions、mutations、state,在文件中创建三个对象

  • actions中要写的是用于响应组件中的动作回调函数,组件通过dispatch方法调用actions中的方法,回调函数接收到的参数有两个(context, value),可以完成一些逻辑,然后将操作传向mutations。
  • mutations中写的是操作state的函数,会被actions和组件通过commit调用,回调函数接收到的参数有两个(state, value)。
  • state中写的就是储存的数据。
  • 下面代码也提到了getters配置项,它就像组件中的computed计算属性,将一些计算后的数据返回,组件可以通过getters点得到想要的内容。

写完配置项之后就可以创建store也就vuex实例了,调用Vuex的Store方法,传入前面写好的四个配置项,然后将new出来的store默认暴露即可,之后在main.js中配置到Vue实例对象上,就可以发现实例对象身上出现了一个$store的值,打开之后就是vuex的方法和state数据。

// store/index.js内容
import Vue from 'vue'
// 引入vuex
import Vuex from 'vuex'
// 使用vuex插件
Vue.use(Vuex)

// 准备actions----用于响应组件中的动作
const actions = {
    incrementOdd(context, value){
        if(context.state.sum % 2) {
            context.commit('INCREMENT', value)
        }
    },
    incrementWait(context, value){
        setTimeout(() => {
            context.commit('INCREMENT', value)
        }, 500);
    },
    addWangStudent(context, value){
        if(value.name[0]!=='王'){
            alert('请添加姓王的同学')
        } else {
            context.commit('ADDSTUDENT', value)
        }
    }
}
// 准备mutations----用于操作数据(state)
const mutations = {
    INCREMENT(state, value){
        state.sum += value
    },
    DECREMENT(state, value){
        state.sum -= value
    },
    ADDSTUDENT(state, value) {
        state.students.unshift(value)
    }
}
// 准备state----用于储存数据
const state = {
    sum:0,
    students:[
        {id:'001', name:'张三'}
    ],
}
// 准备getters----用于将state中的数据进行加工
const getters = {
    bigSum(state){
        return state.sum * 10
    }
}

export default new Vuex.Store({
    actions,
    mutations,
    state,
    getters
})

vuex使用

单模块

配置完之后就可以使用了,在组件中通过$store拿到vuex的数据。

  • 拿到state数据中的sum数据

    this.$store.state.sum
    
  • 拿到getters中的数据

    this.$store.getters.bigSum
    
  • 向actions发送

    this.$store.dispatch('incrementOdd', this.n)
    
  • 向mutations发送

    this.$store.commit('DECREMENT',this.n)
    

上面是最基本的拿到store中的数据。

下面是去拿这些数据的简写方法也就是vuex的一些封装好的方法

  • 导入方法

    import {mapState, mapGetters, mapMutations, mapActions} from 'vuex'
    
  • 拿state和getters数据(将数据通过计算属性拿到之后就可以在模板中直接调用),这里mapState和mapGetters拿到的数据是函数对象,通过...将对象展开到计算属性中。

    computed: {
        // 借助mapState生成计算属性,从state中读取数据。(对象写法)
        // ...mapState({sum:'sum'})
        // 借助mapState生成计算属性,从state中读取数据。(数组写法)
        ...mapState(['sum']),
    
        // 借助mapGetters生成计算属性,从getters中读取数据。(对象写法)
        // ...mapGetters({bigSum:'bigSum'})
        // 借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
        ...mapGetters(['bigSum'])
    },
    
  • 通过mapMutations和mapActions生成调用函数,这里生成的函数可以有传参,不过需要在标签调用时直接传入,否则会将事件event传入。

    methods: {
        // 自己写的方法调用commit
        // increment(){
        //     this.$store.commit('INCREMENT',this.n)
        // },
        // decrement(){
        //     this.$store.commit('DECREMENT',this.n)
        // },
    
        // 借助mapMutations生成对应的方法,方法会调用commit方法联系mutations(对象写法)
        // 需要调用时传参value,否则传参为event
        ...mapMutations({increment:'INCREMENT', decrement:'DECREMENT'}),
        // 借助mapMutations生成对应的方法,方法会调用commit方法联系mutations(数组写法)
        // ...mapMutations(['INCREMENT','DECREMENT'])
    
        // 自己写的方法调用dispatch
        // incrementOdd(){
        //     this.$store.dispatch('incrementOdd', this.n)
        // },
        // incrementWait(){
        //     this.$store.dispatch('incrementWait', this.n)
        // },
        // 借助mapActions生成对应的方法,方法会调用dispatch方法联系actions(对象写法)
        // 需要调用时传参value,否则传参为event
        // ...mapActions({incrementOdd:'incrementOdd', incrementWait:'incrementWait'}),
        // 借助mapActions生成对应的方法,方法会调用dispatch方法联系actions(数组写法)
        ...mapActions(['incrementOdd','incrementWait'])
    },
    
多模块

上面的store配置是单模块的,如果多人开发,就会出现冲突问题,下面通过命名空间多模块,来解决。

index.js中

  • 将两个组件的数据分别配置在两个对象中,打开namespaced配置为true,在下面new store时传入模块。
import Vue from 'vue'
// 引入vuex
import Vuex from 'vuex'
// 使用vuex插件
Vue.use(Vuex)

const countOptions = {
    namespaced:true,
    actions:{
        incrementOdd(context, value){
            if(context.state.sum % 2) {
                context.commit('INCREMENT', value)
            }
        },
        incrementWait(context, value){
            setTimeout(() => {
                context.commit('INCREMENT', value)
            }, 500);
        },
    },
    mutations:{
        INCREMENT(state, value){
            state.sum += value
        },
        DECREMENT(state, value){
            state.sum -= value
        },
    },
    state:{
        sum:0,
    },
    getters:{
        bigSum(state){
            return state.sum * 10
        }
    }
}
const studentOptions = {
    namespaced:true,
    actions:{
        addWangStudent(context, value){
            if(value.name.indexOf('王')===0){
                context.commit('ADDSTUDENT', value)
            } else {
                alert('请添加姓王的同学')
            }
        }
    },
    mutations:{
        ADDSTUDENT(state, value) {
            state.students.unshift(value)
        }
    },
    state:{
        students:[
            {id:'001', name:'张三'}
        ],
    },
    getters:{
        firstStudentName(state){
            return state.students[0].name
        }
    }
}
export default new Vuex.Store({
    modules: {
        countOptions,
        studentOptions
    }
})

组件中调用时

  • 简写方式,在mapState函数中传入第一个参数,也就是模块的命名名称。

    ...mapState('countOptions',['sum']),
    ...mapGetters('countOptions',['bigSum']),
    ...mapMutations('countOptions',{increment:'INCREMENT', decrement:'DECREMENT'}),
    ...mapActions('countOptions',['incrementOdd','incrementWait']),
    
  • 未简写方式

    // 获取state中的数据时需要先获取命名对象,再获取想要的数据
    this.$store.state.countOptions.sum
    // 获取getters时需要在getters的对象名称前加上命名名称/
    this.$store.getters['studentOptions/firstStudentName']
    // 向actions和mutations传时需要修改传入的第一个参数,在方法名前加上命名名称/
    this.$store.commit('studentOptions/ADDSTUDENT', studentObj)
    this.$store.dispatch('studentOptions/addWangStudent', studentObj)
    

标签:value,间通信,state,组件,commit,vuex,store
From: https://www.cnblogs.com/hhhhuaz/p/17566161.html

相关文章

  • 【Spring Cloud Alibaba】毕业组件版本关系
    目录cloud组件版本关系框架版本依赖关系cloud组件版本关系SpringCloudAlibabaVersionSentinelVersionNacosVersionRocketMQVersionDubboVersionSeatacVersion2021.0.1.0*1.8.31.4.24.9.22.7.151.4.22.2.7.RELEASE1.8.12.0.34.6.12.7.131.3.0......
  • element-ui pagination分页组件 点击一次页面跳转触发两次current-change请求
    在项目中使用element编写前端页面时,发现在使用pagination分页组件的时候,出现一个坑。情况是每一次点击页面切换,都会重复触发两次页面切换current-change事件。无论是点击后面的页码或者是下一页或者是跳转到某个页面都会触发两次。第一次正常触发,第二次触发后会返回首页。经过多......
  • vue-pdf组件打印文字全是空白框
    参考:https://www.yii666.com/blog/34226.htmlgithub地址:https://github.com/FranckFreiburger/vue-pdf/pull/130/commits/253f6186ff0676abf9277786087dda8d95dd8ea7#diff-537fb76c67921bef8ccf535dad221c0c875ae6d1077a6b16f055440d32b5421f ......
  • vue-day28--对组件的理解
    学了vue之后,我们需要了解组件是什么组件的定义:实现应用中局部功能代码(css/js/html)和资源(map,map,zip)的集合 1.1模块与组件、模块化与组件化1.1.1模块理解:向外提供特定功能的 js 程序,一般就是一个 js 文件为什么:js 文件很多很复杂作用:复用 js,简化 js 的编写,提......
  • Reactjs学习-组件之间传值
    本篇是关于React的基础-父子组件之间传值子组件想使用父组件的某个属性父组件就需要把这个属性传递给子组件,子组件就可以用this.props.属性名来接收子组件调用父组件的方法父组件就需要把这个方法以属性的方式传递给子组件,子组件就可以用this.属性名来调用,要注意this指向......
  • vue手搓h5滚动日期选择器组件
    背景新项目为了省事和后台写一起了,所以用不了Uni-app(悲),然后element-ui的日期选择器h5不适配,看着也难受,就想找个好用的,结果找了一圈感慨,自己写个吧。 说明 为了加快速度,代码可能有些臃肿,但大概就是这样了,看着代码好多,其实只要会一个的滚动就会多个了。建议下看下参考文章,然后......
  • antd+vue3 tree-select 组件库 筛选结果不正确的问题
    第一次遇到这种带搜索框的下拉树状列表搜索关键字的时候出现我不想要的结果。我感觉组件它只是搜索一级列表而没有搜索二级列表,然后一节列表把它整个的二级列表带出来了。二级列表里边包含搜索关键字的所有item才是我想要的。相关代码:1<!--页面名称-->2<div......
  • 微软计划在 Direct3D 12 新增工作图功能,可解除 GPU 与 CPU 间通信带宽限制
    导读微软计划在3D图形程序开发接口Direct3D12中加入工作图(WorkGraphs)功能,这项功能可解除目前GPU程序开发模型中的限制,让GPU通用运算能够处理更多的工作负载,更广泛地被应用。IT之家注意到,在传统情况下,GPU的工作负载需要由CPU决定,即GPU运算的每一个结果,都需......
  • 前端Vue仿微信我的菜单栏组件按钮组件
    随着技术的发展,开发的复杂度也越来越高,传统开发方式将一个系统做成了整块应用,经常出现的情况就是一个小小的改动或者一个小功能的增加可能会引起整体逻辑的修改,造成牵一发而动全身。通过组件化开发,可以有效实现单独开发,单独维护,而且他们之间可以随意的进行组合。大大提升开发效率......
  • 浅析vue3中如何使用动态组件、如何快速理解Vue3的 toRaw和markRaw、ref与shallowRef、
    一、Vue3中使用component:is加载动态组件1、不使用setup语法糖,这种方式和vue2差不多,is可以是个字符串2、使用setup语法糖,这时候的is如果使用字符串就会加载不出来,得使用组件实例<componentclass="task-box":is="componentObj[route.params.type]":info="taskInfo"></co......