Provide / Inject Scope Demo

点击每个区域的 +1,它们互不影响,不会串起来。

Detail Area

Detail store panel
mode: product-detail
count: 100
label: product-detail: 100
Detail store panel
mode: product-detail
count: 100
label: product-detail: 100

Quick Purchase Area

Quick store panel
mode: quick-purchase
count: 0
label: quick-purchase: 0

结论与解释

provide 可以理解为“向后代组件提供一份共享数据”;inject 可以理解为“后代组件按 key 取这份数据”。 它们用于跨层级传值,避免一层层 props 透传。

SharedPanel 内部调用的是 useScopedCounterStore()(本质是 inject)。 inject 的查找规则是:从当前组件开始,沿着组件树向上逐层查找谁 provide 了对应 key, 找到的第一个祖先就立即返回,这就是“从最近的祖先取值”。

这里的 key 在本 demo 里不是手写字符串,而是 createInjectionState(useScopedCounter) 在内部生成并管理的唯一 key(通常是 Symbol)。provideScopedCounter 和 useScopedCounterStore 共享同一个 key:前者负责 provide,后者负责 inject。

provideScopedCounter 的定义来源在 useScopedCounter.ts(由 createInjectionState 生成并导出),真正执行 provide 的位置在 ScopeProvider.vue(调用 provideScopedCounter(props.initial, props.mode))。

所以规则是:同一个 ScopeProvider 下的多个 SharedPanel 会共享同一份 store; 不同 ScopeProvider 下的 SharedPanel 互不影响;如果出现嵌套 ScopeProvider,内层会覆盖外层(因为更近)。

例子(伪结构):

ScopeProvider(Outer)
├─ SharedPanel-A   // 读取 Outer
└─ ScopeProvider(Inner)
   └─ SharedPanel-B // 读取 Inner(就近优先)