如何使用$语法访问嵌套或命名空间下的Svelte store
核心原因
Svelte的$语法属于编译时预处理的语法糖,编译器仅会识别组件script块顶层作用域内声明的store变量,不会递归解析对象属性中嵌套的store,因此直接访问命名空间对象下的store属性无法触发$语法的自动订阅逻辑。
解决方案:将命名空间对象本身改造为符合契约的store
通过Svelte内置的derived方法聚合所有子store的状态,让默认导出的命名空间对象本身满足store契约(即存在subscribe方法),即可直接用$语法访问聚合后的所有子状态,同时保留原有的方法调用能力。
修改后的User.store.js代码
import { readable, writable, derived } from 'svelte/store'; const store = writable({ token: null, }); const loggedIn = readable(false, (set) => store.subscribe(s => set(!!s.token))); const login = async (token) => store.set({token}); // 修复原代码语法错误:缺失右括号 const logout = async () => store.set({token: null}); const state = {subscribe: store.subscribe} // 聚合所有子store的状态 const rootStore = derived( [state, loggedIn], ([_state, _loggedIn]) => ({ state: _state, loggedIn: _loggedIn }) ) // 合并subscribe、子store、操作方法到默认导出对象 const nameSpacedStore = { // 实现store契约,支持$语法直接作用于该对象 subscribe: rootStore.subscribe, // 暴露原始子store和方法,兼容原有解构导入的用法 state, loggedIn, login, logout } export { state, loggedIn, login, logout } export default nameSpacedStore
组件内使用方式
<script> import NameSpaced from './User.store.js' </script> <!-- 直接生效,返回loggedIn的实时状态 --> LoggedIn: {$NameSpaced.loggedIn} <!-- 也可直接访问基础状态 --> User Token: {$NameSpaced.state.token} <!-- 调用方法逻辑不变 --> <button on:click={() => NameSpaced.login('test_token')}>登录</button>
备选轻量化方案
如果不想改造store导出逻辑,也可以在组件内一次性完成别名解构,避免重复声明:
<script> import NameSpaced from './User.store.js' const { loggedIn: userLoggedIn, state: userState } = NameSpaced </script> LoggedIn: {$userLoggedIn} Token: {$userState.token}
内容的提问来源于stack exchange,提问作者Seltsam
相关产品推荐
相关产品推荐

