Skip to content

概览→拆分详解 ​

本节目标:理解“概览→拆分详解”的核心思路,并能把它用于实际开发或面试表达。

一、最重要的内容(概览) ​

  1. 单例化
    • 不论你在项目中多少次调用 useMarketCalendarStore(),Pinia 只会在第一次调用时执行内部初始化逻辑,后续直接复用同一个实例。
  2. 模块级 vs Store 内部
    • 模块级:所有“全局只需做一次”的工具初始化(如 dayjs.extend)、纯函数、常量,都放在模块顶层。
    • Store 内部:所有响应式状态(ref/reactive)、computed、watch、以及生命周期变量(earliest、registered 等),都放在 defineStore 回调里。
  3. 生命周期步骤
    1. 模块加载:文件被 import 时执行顶层代码(插件注入、defineStore 注册)。
    2. 首次调用:Pinia 创建并初始化 state、watch、任务调度(registerTask)、初次计算(recalcAll)。
    3. 后续调用:直接返回已有实例,不再重复初始化。

二、详细拆解 ​

1. 模块加载阶段 ​

  • 发生时机:脚本第一次被 import(打包或运行时)
  • 做了什么:
    ts
    dayjs.extend(utc)
    dayjs.extend(timezone)
    const useMarketCalendarStore = defineStore('marketCalendar' /* ↓ 回调未执行 */)
    • 插件注册:dayjs 时区扩展只做一次;
    • Store 注册:defineStore 将你的回调函数挂到 Pinia,尚未执行回调内部逻辑。

2. 首次调用** **useMarketCalendarStore() ​

  • 发生时机:应用中第一次执行 useMarketCalendarStore()
  • 做了什么:
    1. 创建响应式状态:
      ts
      const symbolSessions = ref<Map<string, MarketSession[]>>(new Map())
      const holidays = ref<Set<string>>(new Set())
      // … 等其它 state、computed、reactive、watch
    2. 挂载 watcher:
      • 监听 symbolSessionMap 的变化,自动调整下一次调度时间;
      • 监听 accountStore.selectedAccount,切换账号时可重新拉取节假日。
    3. 注册任务调度:
      ts
      registerTask('__all__', initNow.add(1, 'second'), () => recalcAll(dayjs()))
      recalcAll(initNow) // 初始化计算一次所有 symbol 的状态
    4. 设置内部标记:registered = true,以后不再重复走注册逻辑。 > 注释示例 > > ```ts

// 初始化:拉取所有 symbol 状态,并注册定时任务 registerTask('all', initNow.add(1, 'second'), () => recalcAll(dayjs()))

3. 后续再次调用** **useMarketCalendarStore() ​

  • 发生时机:除首次外的所有调用
  • 行为:
    • Pinia 直接返回已创建好的 store 实例;
    • 不会重新执行回调,不会重复创建 state、watch 或 注册任务。

4. 模块级 vs Store 内部的设计取舍 ​

内容类别放在模块顶层(module-level)放在 defineStore 回调内部
一次性全局初始化dayjs.extend(utc)、工具函数引用、常量
纯函数/常量getSymbolMarketStatus、toHHMM 等
响应式状态ref、reactive、computed
副作用/Watcherwatch(...)
局部生命周期变量earliest、registered、known 等

5. 核心流程图(伪代码) ​

模块加载 → defineStore 注册 首次调用 store → ├─ 创建 state/computed/watch ├─ registerTask → 定时 recalcAll └─ recalcAll 初始化所有 market 状态 后续调用 store → 直接返回实例

通过以上“先概览再拆解”的方式,你可以快速把握 Pinia store 的执行要点,也能清楚地把握哪些逻辑适合放在模块级、哪些必须放到 store 内部。这样一来,既保证了性能(避免重复初始化),又保持了状态管理的清晰与可维护性。

本站总访问 — 次