vue3: 2.如何利用 effectScope 自己实现一个青铜版pinia 一 getters篇

2023-11-21 14:50

本文主要是介绍vue3: 2.如何利用 effectScope 自己实现一个青铜版pinia 一 getters篇,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

vue3: 如何利用 effectScope 自己实现一个青铜版pinia - getters篇

上一篇 我们实现了状态管理仓库的 state, pinia和vuex中都有计算属性getters, 接下来我们就来实现计算对象 getters

我们都知道getters具有计算属性,依赖于其他state和 getter 值进行计算新的值
如何在store中实现这个效果,vue3中有一个cumputed api可以让我们使用

上代码:
依然是创建一个store对象,store新增一个getters对象
我们写getters的时候是一个函数,函数的返回值才是最终使用的数据
那么我们可以在useStore 第一次执行的时候利用 computed 将getters 里面的所有函数执行并返回一个新的getters对象,该对象也是具有响应式的
得到新的getters对象后我们将getters对象合并到store.state 对象上
组件中使用getters上的属性时可以直接通过 store.state[gettersNmae] 访问

const store = {state: {val: 0},getters: {computedVal (state) {return state.val + 1// 或者直接通过this访问// 为何可以通过this访问,请查看getters合并到state的操作// 原理就是利用call函数将this对象指向了store.state 对象// return this.val + 1},computedVal2 (state) {// 直接访问 计算属性 computedValreturn this.computedVal + 1}},useStore () {const setUp = () => {if (!Vue.isReactive(this.state)) {// 以下的操作只需要执行一次// 因为执行setup做响应式依赖收集的时候会在每个组件执行,访问的是同一个state,该state 对象的代理实现只需要第一次就够了this.state = Vue.reactive(this.state)const _this = this// 将this.getters里面的函数取出,存到 getters 这个对象里面的值变为具有computed 计算属性的一个对象const getters = Object.keys(_this.getters || {}).reduce(function (conmputedGetters, name) {// 利用computed 计算this.getters里面的值, 并记录下来conmputedGetters[name] = Vue.computed(() => {return _this.getters[name].call(_this.state, _this.state)})return conmputedGetters}, {})// 合并 getters对象 到 this.stateObject.assign(this.state, getters)}}const scope = Vue.effectScope()scope.run(setUp)return this.state}
}

然后我们创建两个子组件并使用这个store的getters

<body><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.37/vue.global.min.js"integrity="sha512-rCO3ZZnxh9j/Y725Iq2Cqr2lc9fi83zVeN3PFTUosktylZsCFjD13PDbKrzKjKO/idjM4KlMQC52AsoGFTAe6A=="crossorigin="anonymous"referrerpolicy="no-referrer"></script><div id="app"></div><script>// 实现一个gettersconst store = {state: {val: 0},getters: {computedVal (state) {return state.val + 1// 或者直接通过this访问// 为何可以通过this访问,请查看getters合并到state的操作// 原理就是利用call函数将this对象指向了store.state 对象// return this.val + 1},computedVal2 (state) {// 直接访问 计算属性 computedValreturn this.computedVal + 1}},useStore () {const setUp = () => {if (!Vue.isReactive(this.state)) {// 以下的操作只需要执行一次// 因为执行setup做响应式依赖收集的时候会在每个组件执行,访问的是同一个state,该state 对象的代理实现只需要第一次就够了this.state = Vue.reactive(this.state)const _this = this// 将this.getters里面的函数取出,存到 getters 这个对象里面的值变为具有computed 计算属性的一个对象const getters = Object.keys(_this.getters || {}).reduce(function (conmputedGetters, name) {// 利用computed 计算this.getters里面的值, 并记录下来conmputedGetters[name] = Vue.computed(() => {return _this.getters[name].call(_this.state, _this.state)})return conmputedGetters}, {})// 合并 getters对象 到 this.stateObject.assign(this.state, getters)}}const scope = Vue.effectScope()scope.run(() => {// 执行setup函数,收集响应式依赖return setUp()})return this.state}}// 子组件1const childrenOne = Vue.defineComponent({name: 'children-one',setup () {// 为什么要执行useStore,因为要通过 useStore 内的setup 函数为该组件提供响应式的依赖搜集// storeA 已经是一个包含getters的最基本的状态管理对象了// 不过我们一般不建议直接修改store的值,后续会提供actions去帮助大家更改state的值const storeA = store.useStore()const add = () => {storeA.val += 1}return {add,storeA}},template: `<div><h3>children-one</h3><button @click="add">children-one add</button><br/><span>计算属性 computedVal: {{storeA.computedVal}}</span><br/><span>计算属性 computedVa2l: {{storeA.computedVal2}}</span></div>`})// 子组件2const childrenTwo = Vue.defineComponent({name: 'children-two',setup () {const storeB = store.useStore()const remove = () => {storeB.val -= 1}return {remove,storeB}},template: `<div><h3>children-two</h3><button @click="remove">children-two remove</button><br/><span>计算属性 computedVal: {{storeB.computedVal}}</span><br/><span>计算属性 computedVa2l: {{storeB.computedVal2}}</span><br/></div>`})const app = Vue.createApp({name: 'app',components: {'children-one': childrenOne,'children-two': childrenTwo,},template: `<div class='ass' ><children-one /><children-two /></div>`})app.mount('#app')</script>
</body>

我们来看下效果:

在这里插入图片描述

这样一个我们就实现计算属性 getters

但是实际应用中并不推荐我们直接更改store.state的值
包括vuex中在mutions之外更改state的值也会警告
况且pinia中组件里面gettes属性的读取都是通过store.state对象直接读取的
在开发过程中 store.state.val = xxx 这样更改状态是非常不可控的
如果getters的computedVal值被这样赋值 store.state.computedVal = xxx,他将会失去计算属性和响应式

所以我们还需要一个能够修改状态的actions,这就是我在下一篇讲要讲的内容了

这篇关于vue3: 2.如何利用 effectScope 自己实现一个青铜版pinia 一 getters篇的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/403023

相关文章

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

Redis客户端连接机制的实现方案

《Redis客户端连接机制的实现方案》本文主要介绍了Redis客户端连接机制的实现方案,包括事件驱动模型、非阻塞I/O处理、连接池应用及配置优化,具有一定的参考价值,感兴趣的可以了解一下... 目录1. Redis连接模型概述2. 连接建立过程详解2.1 连php接初始化流程2.2 关键配置参数3. 最大连

Python实现网格交易策略的过程

《Python实现网格交易策略的过程》本文讲解Python网格交易策略,利用ccxt获取加密货币数据及backtrader回测,通过设定网格节点,低买高卖获利,适合震荡行情,下面跟我一起看看我们的第一... 网格交易是一种经典的量化交易策略,其核心思想是在价格上下预设多个“网格”,当价格触发特定网格时执行买

python设置环境变量路径实现过程

《python设置环境变量路径实现过程》本文介绍设置Python路径的多种方法:临时设置(Windows用`set`,Linux/macOS用`export`)、永久设置(系统属性或shell配置文件... 目录设置python路径的方法临时设置环境变量(适用于当前会话)永久设置环境变量(Windows系统

Python对接支付宝支付之使用AliPay实现的详细操作指南

《Python对接支付宝支付之使用AliPay实现的详细操作指南》支付宝没有提供PythonSDK,但是强大的github就有提供python-alipay-sdk,封装里很多复杂操作,使用这个我们就... 目录一、引言二、准备工作2.1 支付宝开放平台入驻与应用创建2.2 密钥生成与配置2.3 安装ali

Spring Security 单点登录与自动登录机制的实现原理

《SpringSecurity单点登录与自动登录机制的实现原理》本文探讨SpringSecurity实现单点登录(SSO)与自动登录机制,涵盖JWT跨系统认证、RememberMe持久化Token... 目录一、核心概念解析1.1 单点登录(SSO)1.2 自动登录(Remember Me)二、代码分析三、

PyCharm中配置PyQt的实现步骤

《PyCharm中配置PyQt的实现步骤》PyCharm是JetBrains推出的一款强大的PythonIDE,结合PyQt可以进行pythion高效开发桌面GUI应用程序,本文就来介绍一下PyCha... 目录1. 安装China编程PyQt1.PyQt 核心组件2. 基础 PyQt 应用程序结构3. 使用 Q

Python实现批量提取BLF文件时间戳

《Python实现批量提取BLF文件时间戳》BLF(BinaryLoggingFormat)作为Vector公司推出的CAN总线数据记录格式,被广泛用于存储车辆通信数据,本文将使用Python轻松提取... 目录一、为什么需要批量处理 BLF 文件二、核心代码解析:从文件遍历到数据导出1. 环境准备与依赖库

linux下shell脚本启动jar包实现过程

《linux下shell脚本启动jar包实现过程》确保APP_NAME和LOG_FILE位于目录内,首次启动前需手动创建log文件夹,否则报错,此为个人经验,供参考,欢迎支持脚本之家... 目录linux下shell脚本启动jar包样例1样例2总结linux下shell脚本启动jar包样例1#!/bin

go动态限制并发数量的实现示例

《go动态限制并发数量的实现示例》本文主要介绍了Go并发控制方法,通过带缓冲通道和第三方库实现并发数量限制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录带有缓冲大小的通道使用第三方库其他控制并发的方法因为go从语言层面支持并发,所以面试百分百会问到