简单自定义vuex的设计思路

vuex集中式存储管理应用所有组件的状态,并以响应的规则保证状态以可预测的方式 发生变化。

步骤:

1.Store类,保存选项,_mutations,_actions,getters

2.响应式状态:new Vue方式设置响应式。

3.get state 和 set state commit dispatch

4.install方法 挂载store到vue的原型对象上,所有实例都可以读取到。

生成Vuex类

说到底,vuex也还是个插件,所以生成一个类,按照使用插件的形式将其export导出。

挂载到Vue实例上我们还是使用mixin的方式,原理和vue-router的自定义方式一致,这里就不多说了。

let Vue

class Store{
    constructor(options){
        //保存选项

        // state为响应式数据
        this.state = new Vue({
            data:options.state
        })
    }
}

function install(_Vue){
    Vue = _Vue
    //挂载$store给外面使用
    Vue.mixin({
        beforeCreate() {
            if(this.$options.store){
                //挂载到vue原型上,每个vue实例都可以访问到
                Vue.prototype.$store = this.$options.store
            }
        },
    })
}

export default {
    Store,install
}

但是在这里,我们使用new Vue的data属性来让state成为一个响应式的数据,有个弊端就是能够直接的修改data里的数据,那这样违反了vuex单向数据流的特点,那么我们要封装一下。

官网解释,有两个的$变量就不做代理,所以也就不会再_vm的根上访问到$$state这个属性,同时设置set get俩属性,get为只读,那么外面就无法修改state的值,只能通过commit或actions进行修改。_vm下的响应式对象会挂载在_data的对象上,_vm下的$data是一个原始对象,不具备响应式,所以使用_data。

如下图,$data不存在observer

class Store{
    constructor(options){
        //保存选项
        // state为响应式数据
        this._vm = new Vue({
            data:{
                $$state:options.state
            }
        })
    }
    //给用户暴露接口
    get state(){
        console.log(this._vm);
        return this._vm._data.$$state
    }
    set state(val){
        throw Error('replaceSate')
    }
}

commit和dispatch

响应式的数据发生变化就会引起render函数渲染数据 ,在commit中会接收到参数,我们在构造函数中存储传入的mutations和actions,然后在commit和dispach中匹配到详情的操作,然后执行。

但是在执行过程中有坑,this的指向问题:当前的调用是在外部,所以指向的是外部的store实例,是没有commit等参数,所以没有办法调用到。需要在constructor存储上下文,并且改变this指向到当前的实例,获取到对应的上下文即可。

class Store{
    constructor(options){
        //保存选项
        this._mutations  = options.mutations||{}
        this._actions  = options.actions||{}
        // state为响应式数据
        this._vm = new Vue({
            data:{
                $$state:options.state
            }
        })
        //上下文的绑定
        this.commit=this.commit.bind(this)
        this.dispatch=this.dispatch.bind(this)
    }
    //给用户暴露接口
    get state(){
        return this._vm._data.$$state
    }
    set state(val){
        throw Error('replaceSate')
    }
    //store.commit(type,payload)
    commit(type,payload){
        //获取mutitions
        const entry = this._mutations[type]
        if(!entry){
            console.error('unknown mutition type');
        }
        entry(this.state,payload)
    }
    dispatch(type,payload){
        const entry = this._actions[type]
        if(!entry){
            console.error('unknown actions type');
        }
        console.log(this);
        entry(this,payload)//注意这里的this指向问题,当前的调用是在外部,所以指向的是外部的store实例,是没有commit等参数,所以没有办法调用到。需要在constructor存储上下文,并且改变this指向。
    }
}

getters

getters我们可以借助computed属性,只可获取不可更改,获取到getters的key给到computed,并且在给一个函数,在其内部调用fn并且传入state,再将computed属性进行响应式处理。

this._wrappedGetters  = options.getters||{}
        //定义computed选项
        const computed={}
        this.getters={}
        const store= this
        Object.keys(this._wrappedGetters).forEach(key=>{
            //获取用户定义的getter
            const fn = store._wrappedGetters[key]
            // 转换为computed可以使用的无参数形式
            computed[key]=function(){
                return fn(store.state)
            }
            //为getters定义只读属性
            Object.defineProperty(store.getters,key,{
                get:()=>{
                    return store._vm[key]
                }
            })
        })

        // state为响应式数据
        this._vm = new Vue({
            data:{
                $$state:options.state
            },
            computed
        })

附完整代码:

let Vue

class Store{
    constructor(options){
        //保存选项
        this._mutations  = options.mutations||{}
        this._actions  = options.actions||{}
        this._wrappedGetters  = options.getters||{}
        //定义computed选项
        const computed={}
        this.getters={}
        const store= this
        Object.keys(this._wrappedGetters).forEach(key=>{
            //获取用户定义的getter
            const fn = store._wrappedGetters[key]
            // 转换为computed可以使用的无参数形式
            computed[key]=function(){
                return fn(store.state)
            }
            //为getters定义只读属性
            Object.defineProperty(store.getters,key,{
                get:()=>{
                    return store._vm[key]
                }
            })
        })

        // state为响应式数据
        this._vm = new Vue({
            data:{
                $$state:options.state
            },
            computed
        })
        //上下文的绑定
        this.commit=this.commit.bind(this)
        this.dispatch=this.dispatch.bind(this)
    }
    //给用户暴露接口
    get state(){
        return this._vm._data.$$state
    }
    set state(val){
        throw Error('replaceSate')
    }
    //store.commit(type,payload)
    commit(type,payload){
        //获取mutitions
        const entry = this._mutations[type]
        if(!entry){
            console.error('unknown mutition type');
        }
        entry(this.state,payload)
    }
    dispatch(type,payload){
        const entry = this._actions[type]
        if(!entry){
            console.error('unknown actions type');
        }
        entry(this,payload)//注意这里的this指向问题,当前的调用是在外部,所以指向的是外部的store实例,是没有commit等参数,所以没有办法调用到。需要在constructor存储上下文,并且改变this指向。
    }
}

function install(_Vue){
    Vue = _Vue

    //挂载$store给外面使用
    Vue.mixin({
        beforeCreate() {
            if(this.$options.store){
                //挂载到vue原型上,每个vue实例都可以访问到
                Vue.prototype.$store = this.$options.store
                
            }
        },
    })
}

export default {
    Store,install
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/223080.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

电脑开机提示“未正确启动”怎么办?

有时我们在打开电脑时,会出现蓝屏,并提示“电脑未正确启动”,那么,这该怎么办呢?下面我们就来了解一下。 方法一:执行系统还原 我们在上文中提到了Windows无法正确启动的问题可能是由于三方程序或者近期的…

Java利用TCP实现简单的双人聊天

一、创建新项目 首先创建一个新的项目,并命名为聊天。然后创建包,创建两个类,客户端(SocketClient)和服务器端(SocketServer) 二、实现代码 客户端代码: package 聊天; import ja…

Spring Boot 3.2项目中使用缓存Cache的正确姿势!!!

你是否曾想过为什么在 Spring Boot 应用中缓存是如此重要?答案在于它通过减少数据检索时间来提高性能。在本文中,我们将深入探讨缓存对微服务模式的影响,并探讨根据操作易用性、速度、可用性和可观测性等因素选择正确缓存的重要性。我们还将探…

[RISCV] 发现一个可以看RISC-V CPU行为的开源项目

最近在浏览某大型程序员交友 网站的时候发现一个好玩的项目,介绍如下: A small program that handles mie, msi, mti and trap interrupts and updates some global variables on interrupts. 重点是他下面还放了一张图: 能看到RISCV CSR的行为太酷啦!!! 下面一起setup一…

Sourcepawn脚本入门(二)命令与事件监听

🍎Sourcepawn脚本入门(二)命令与事件监听 (控制台)命令是常用的插件形式,eg. noclip …等都是常用的命令,在游戏中使用也很容易,souremod可以注册自己的命令。 事件的监听则需要考虑到不同的起源游戏支持的事件不同&am…

中文BERT模型预训练参数总结以及转化为pytorch的方法

1.目前针对中文的bert预训练模型有三家: 谷歌发布的chinese_L-12_H-768_A-12 还有哈工大的chinese-bert-wwm / chinese-bert-wwm-ext 以及HuggingFace上的bert-base-chinese(由清华大学基于谷歌的BERT在中文数据集上训练开发的模型,上传在HuggingFace) …

彻底删除VsCode配置和安装过的插件与缓存

前言 当你准备对 Visual Studio Code(VSCode)进行重新安装时,可能遇到一个常见问题:重新安装后,新的安装似乎仍然保留了旧的配置信息,这可能会导致一些麻烦。这种情况通常是由于卸载不彻底所致&#xff0c…

【LVS实战】04 LVS+Keepalived实现负载均衡高可用

一、介绍 Keepalived 是一个用于 Linux 平台的高可用性软件。它实现了虚拟路由器冗余协议 (VRRP) 和健康检查功能,可以用于确保在多台服务器之间提供服务的高可用性。Keepalived 可以检测服务器的故障,并在主服务器宕机时,自动将备份服务器提…

外卖系统源码开发:打造高效智能化餐饮解决方案

在当今数字化时代,外卖系统成为了餐饮业中不可或缺的一部分。为了满足日益增长的外卖需求,我们将深入探讨外卖系统源码开发的关键技术和创新应用。 1. 技术栈选择 在开始外卖系统源码的开发之前,我们首先需要选择适用的技术栈。一个典型的…

【langchain实战】开源项目-RasaGPT

1、概述 RasaGpt是一个建立在 Rasa 和 Langchain 之上的没有显示界面的LMM聊天机器人平台。它是一个Rasa和Telegram这种利用像Langchain这样的LMM库进行索引、检索和上下文注入的样板及参考实现。 开源地址: GitHub - paulpierre/RasaGPT: 💬 RasaGPT is…

揭秘:软件测试中Web请求的完整流程!

在软件开发的过程中,测试是一个至关重要的环节。而在现代互联网应用中,Web请求是很常见的一个测试需求。本文将介绍Web请求的完整测试流程,帮助读者更好地理解软件测试的关键步骤。 一、测试准备阶段 在进行Web请求测试之前,测试团…

【CMake入门】第二节——CMake常用指令介绍

系列文章: 【CMake入门】第一节——CMake的安装与简单样例 CMake常用指令介绍 cmake_minimum_required 指定要求最小的cmake版本,如果版本小于该要求,程序终止 project(test) 设置当前项目名称为test CMAKE_BUILD_TYPE 用于设置CMake构…

招商银行薪福:一站式API连接电商平台,实现CRM与客服系统集成

招商银行薪福通的API集成优势 招商银行的SaaS产品薪福通在电商行业迅速崭露头角,它通过一站式API连接,极大地简化了电商平台与CRM及客服系统的集成过程。企业无需深入研究API开发细节,也不必担心代码复杂性,就能实现系统间的高效…

LeetCode力扣每日一题(Java):14、最长公共前缀

一、题目 二、解题思路 1、我的思路 乍一看我的代码量还是比较少,但是提交上去发现时间效率和空间效率都不占优势 讲讲我的思路:首先通过for循环找出数组中长度最短的字符串,并用min储存最短字符串的长度,最长公共前缀不可能比…

SAP MM 中的业务伙伴确定配置

这篇博客文章将概述 SAP MM 供应商帐户组中的合作伙伴确定是什么以及如何在 S/4 系统中配置它。 本文将指导您完成分步过程,并为您提供有关在供应商主数据中使用合作伙伴确定的完整想法。 合作伙伴角色 供应商在 SAP 中扮演着不同类型的角色,让我们通…

基于JavaSwing实现的学生管理系统(课程设计必备)

基于JavaSwing实现的学生管理系统,最全的Java基础学生管理系统,Java课程设计必备 系统一共包括学生信息管理,考勤签到管理,学生成绩管理,学生选课管理系统。不仅有基础功能,还有图表统计等功能。功能是非常…

记录 | chrome下载提速

chrome浏览器下载提速的方法: 谷歌浏览器一直都带有多线程下载模式,只不过默认关闭了,打开后下载速度会提升很多,只要在新标签页输入 chrome://flags/#enable-parallel-downloading ,点enter,出现下图点击…

逆向修改Unity的安卓包资源并重新打包

在上一篇文章中,我已经讲过如何逆向获取unity打包出来的源代码和资源了,那么这一节我将介绍如何将解密出来的源代码进行修改并重新压缩到apk中。 其实在很多时候,我们不仅仅想要看Unity的源码,我们还要对他们的客户端源码进行修改和调整,比如替换资源,替换服务器连接地址…

智能优化算法应用:基于梯度算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于梯度算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于梯度算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.梯度算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…

Beam Search学习

BackGround 在生成的时候,模型的输出是一个时间步一个时间步依次获得的,而且前面时间步的结果还会影响后面时间步的结果。也就是说,每一个时间步,模型给出的都是基于历史生成结果的条件概率。 为了生成完整的句子,需…
最新文章