VueUse 学习 —— createGlobalState

1,835 阅读2分钟

createGlobalState是VueUse库中提供的一个函数,它用于创建全局状态。在Vue中,可以使用provide/inject或Vuex来实现全局状态的管理,但是在某些简单的场景下,使用这些方案可能会过于繁琐。而createGlobalState则提供了一种更加简单的方式来管理全局状态。

createGlobalState函数接收一个参数,即全局状态的初始值,并返回一个数组。数组中的第一个元素为状态值,第二个元素为修改状态的函数。我们可以将这个数组用provide/inject方式提供给子组件使用。

例如,下面的示例代码使用createGlobalState来管理一个全局的计数器:

import { createGlobalState } from 'vueuse';

// 创建全局状态
const useCounter = createGlobalState(0);

// 父组件中使用状态
export default {
  setup() {
    const [count, setCount] = useCounter();
    
    function increment() {
      setCount(count.value + 1);
    }
    
    return {
      count,
      increment,
    };
  },
};

// 子组件中使用状态
export default {
  setup() {
    const [count] = useCounter();
    
    return {
      count,
    };
  },
};

源码分析

源码如下:

import { effectScope } from 'vue-demi'
import type { AnyFn } from '../utils'

/**
 * Keep states in the global scope to be reusable across Vue instances.
 *
 * @see https://vueuse.org/createGlobalState
 * @param stateFactory A factory function to create the state
 */
export function createGlobalState<Fn extends AnyFn>(
  stateFactory: Fn,
): Fn {
  let initialized = false
  let state: any
  const scope = effectScope(true)

  return ((...args: any[]) => {
    if (!initialized) {
      state = scope.run(() => stateFactory(...args))!
      initialized = true
    }
    return state
  }) as Fn
}

这段代码定义了一个名为 createGlobalState 的函数,该函数接受一个函数作为参数,用于创建一个全局状态。

该函数利用了 Vue.js 的 effectScope API 来创建一个作用域,并将状态存储在该作用域中,以便在全局范围内重用。

createGlobalState 函数返回一个函数,该函数接受任意数量的参数,并在第一次调用时执行 stateFactory 函数以创建初始状态,并将该状态保存在闭包变量 state 中,之后再次调用该函数时直接返回已经创建好的状态。 由于 TypeScript 中的类型推断,该返回的函数的类型与传入的 stateFactory 函数的类型相同。

该实现还定义了两个变量:initialized 用于标记全局状态是否已经初始化,state 用于保存全局状态。在第一次调用返回的函数时,initialized 变量将设置为 true,并使用 effectScope 创建一个作用域来运行 stateFactory 函数以获取初始状态,并将该状态存储在 state 变量中。此后再次调用该返回的函数时,它将直接返回已经创建好的状态。