闭包实现一个简单Vue3的状态管理

概述

在vue3中,项目里面使用状态管理,有两种选择,Pinia 和 Vuex 都是 Vue 的状态管理库,官方更加推荐pinia,因为其API的使用更加简洁方便,我们在项目里面通过hook方式快速方便的接入。

pinia示例

pinia提供两种store的使用方式

Option Store

与 Vue 的选项式 API 类似,我们也可以传入一个带有 stateactionsgetters 属性的 Option 对象

js 复制代码
export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0, name: 'Eduardo' }),
  getters: {
    doubleCount: (state) => state.count * 2,
  },
  actions: {
    increment() {
      this.count++
    },
  },
})

setup Store(推荐)

也存在另一种定义 store 的可用语法。与 Vue 组合式 API 的 setup 函数 相似,我们可以传入一个函数,该函数定义了一些响应式属性和方法,并且返回一个带有我们想暴露出去的属性和方法的对象。

js 复制代码
export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  const name = ref('Eduardo')
  const doubleCount = computed(() => count.value * 2)
  function increment() {
    count.value++
  }

  return { count, name, doubleCount, increment }
})

自定义实现

我们基于上面setup Store的方式实现一个类似的我们自己的store,因为这种方式更加符合组合式API的特性,我们使用和编写对应代码也更加简单方便,核心为闭包函数,不了解js闭包函数的,可以先学习下相关概念。主要应用闭包函数如下特性:

  1. 记忆环境:闭包可以记住创建时的词法环境
  2. 保持变量:闭包可以让局部变量在函数执行完后仍然保持在内存中
  3. 私有性:闭包可以用来创建私有变量和方法

效果

具体实现

定义store

新建store/useCounter.js

js 复制代码
import { computed, ref } from "vue";

// 定义store
export const useCounterStore = defineStore(() => {
    const count = ref(0);
    const doubleCount = computed(() => count.value * 2);
    function increment() {
        count.value++;
    }

    return { count, doubleCount, increment };
});



// 闭包函数缓存
function defineStore(fn) {
    let state = null
    return () => {
        if (!state) {
            state = fn()
        }
        return state
    }
}

使用

新增Test.vue组件,导入store使用

js 复制代码
<script setup lang="ts">
import { useCounterStore } from "../hook/useCounter";
const { count, doubleCount, increment } = useCounterStore();
</script>
<template>
  <div>
    <h2>Test组件</h2>
    <p>count:{{ count }}</p>
    <p>doubleCount:{{ doubleCount }}</p>
    <button @click="increment">递增</button>
  </div>
</template>

APP中引入测试组件

js 复制代码
<template>
    <Test></Test>
    <Test></Test>
    <Test></Test>
</template>

总结

如上所示,我们自定义的store可以和pinia的setup Store一样的用法,唯一不同在于,pinia第一个参数用作store的id使用,我们自己使用时没有用到了,官方Pinia 将用它来连接 store 和 devtools,因此本地我们自己实现就没必要了,实现核心在于闭包函数,多数工具库中是非常常见的用法。

相关推荐
小雨下雨的雨几秒前
鸿蒙PC用Electron框架——Canvas蜡笔抖动效果实现技术深度解析
前端·javascript·华为·electron·鸿蒙系统
ZC跨境爬虫2 分钟前
跟着 MDN 学CSS day_49:定位实例练习从入门到精通
前端·css·学习
前端小万2 分钟前
用AI两小时开发上架的小程序,单日新增用户173
前端·微信小程序
道友可好6 分钟前
Spec Kit:GitHub 官方出品,规范即代码
前端·人工智能·后端
木斯佳10 分钟前
前端八股文面经大全:磐松私募-27届前端实习一面(2026-05-27)·面经深度解析
前端
薛先生_09914 分钟前
声明式导航(route-link)(跳转传参)
前端
郑州光合科技余经理18 分钟前
海外版外卖系统:如何快速搭建国际化外卖平台
java·开发语言·前端·人工智能·小程序·系统架构·php
小雨下雨的雨26 分钟前
蜡笔小画家鸿蒙PC用Electron框架 - 儿童学画蜡笔画技术实现详解
前端·javascript·华为·electron·前端框架·交互·鸿蒙系统
天蓝色的鱼鱼26 分钟前
别只拿 Playwright 写测试,这三个野路子用法才是真香
前端
SoaringHeart29 分钟前
Flutter进阶|源码修改:DecorationImage 添加网络图片占位图
前端·flutter