前端开发避坑--在组件外使用 pinia 实例的同时,避免持久化无效

简介

pinia 官网介绍了在组件外使用 pinia 实例的方式并不适用于所有场景,只是希望开发者能在实例创建好并注册到 app 实例后再使用 use*Store 获取对应仓库的实例。

这是链接:https://pinia.vuejs.org/zh/core-concepts/outside-component-usage.html#single-page-applications

需求说明

我的需求是在创建 i18n 实例前,先判定本地是否有持久化的语言状态,没有时才取项目的默认语言。同时,为了规范在项目中使用 i18n 获取各组件独立的以及通用的文本,还需要导出创建好的 i18n 实例给对应的模块。

问题分析

一开始使用了这个链接提到的方法,在 /store 目录下新建了一个方便获取的函数:

import { store } from './index';

const getStoreOutsideVue = (useStoreHook) => useStoreHook(store);
export default getStoreOutsideVue;

然后,在 i18n 的初始化模块中,引入该函数以及保存语言状态的仓库 useLocaleStore 并调用。

重新生成的页面确实能获取到持久化状态了,但一刷新就发现持久化状态不再更新了。检查后发现其他没有被 i18n 引入的仓库都正常,说明问题是出在了这里的 getStoreOutsideVue 调用上。

查资料后,看到有种说法是 当项目中存在多个 Pinia 实例时,持久化可能会失效。虽然不确定这里是否确实是这个原因,但该问题确实暂时解决不了,因此重新回到官网的建议上。

分析我的需求,区别在于原先的 i18n 实例初始化逻辑中,有一个 setupI18nConfigs 函数,该函数会在 i18n 模块中直接调用并将结果传递给 createI18n 函数,因此项目中的 i18n 实例是在该模块中同步创建的。在这种方式下,我无法确保 i18n 实例的创建过程必定在 pinia 实例的注册过程之后。

因此,考虑是否能调整初始化逻辑的时间。

由于 i18n 模块以及其他模块的注册过程是参考了 vben-admin 的源码,因此,尝试到该项目中寻找解决方案,也确实找到了,而且挺简单的。

vben-admin 的思路是先创建一个空的 i18n 变量,然后在 setupI18n 函数中再去调用 setupI18nConfigs 以及 createI18n 创建实例并赋值。这样,全局仍然只有一个 i18n 实例,同时,又能确保该实例的初始化过程在 pinia 实例注册之后执行。

总结

需求本身并不复杂,解决的措施也很简单,但还是花了一些时间才从其他人的思路中得到启发。

写 vue3 大部分时候用到的都是 const 声明的变量,产生了下意识的依赖,不太敢用 let 关键字了,怕一不小心修改了代理对象的引用导致丢失响应性。

总结一句话,还是需要多看优质源码,学习他人的思路,突破自身思维的局限性。

posted @ 2022-12-09 21:02  CJc_3103  阅读(1792)  评论(0编辑  收藏  举报