跳转到内容

全局状态管理

刀刀
0字
0分钟
2026/8/16

小项目或对代码体积有要求的项目,可能不希望引入PiniaVuex 等全局状态管理库,而是自己实现一个简单的全局状态管理。

实现

通过闭包将状态存储,使用时拿到之前存储的值。第一次调用时无数据,触发一次回调函数;后续调用时直接返回之前存储的返回值。

js
import { ref } from 'vue'

export const useCounter = defineStore(() => {
  const count = ref(1)
  const addFn = () => {
    count.value++
  }
  return {
    count,
    addFn,
  }
})

function defineStore(fn) {
  let state
  return () => {
    if (state) return state
    return (state = fn())
  }
}
vue
<script setup>
import { useCounter } from './store/counter.js'
import Father from './components/Father.vue'
import Son from './components/Son.vue'

const { count } = useCounter()
</script>

<template>
  <h1>{{ count }}</h1>
  <Father />
  <Son />
</template>
vue
<script setup>
import { useCounter } from './store/counter.js'

const { count, addFn } = useCounter()
</script>

<template>
  <h3>Father: {{ count }}</h3>
  <button @click="addFn">add</button>
</template>
vue
<script setup>
import { useCounter } from './store/counter.js'

const { count } = useCounter()
</script>

<template>
  <div>Son: {{ count }}</div>
</template>

细化

js
import { ref, getCurrentScope, effectScope } from 'vue'

export const useCounter = defineStore(() => {
  const count = ref(1)
  const addFn = () => {
    count.value++
  }
  const scope = getCurrentScope() 
  return {
    count,
    scope, 
    addFn,
  }
})

function defineStore(fn) {
  let state
  return () => {
    if (state) return state
    const scope = effectScope(true) 
    return (state = scope.run(fn)) 
  }
}

通过 effectScope 创建闭包,将状态存储在闭包中。defineStore 返回的函数第一次调用时执行 effectScope 中的函数,将状态存储并返回;第二次调用时直接返回之前存储的状态。

effectScope 用于创建作用域,作用域中的变量和函数在作用域销毁后会自动清理。它用于分组和管理多个响应式 effect,解决复杂场景下组织和清理 effect 的问题。

动手实操

跳转预览:点击跳转

贡献者

The avatar of contributor named as duyidao duyidao
The avatar of contributor named as 刀刀 刀刀
The avatar of contributor named as v_duyilin v_duyilin

页面历史

刀刀博客累计访客 人;文档累计访问量共