pinia 踩坑总结

简介: pinia 踩坑总结

网络异常,图片无法展示
|


最近在做项目调优,一个 Vue3 项目当初使用 vuex 做的状态管理,最近大家都在谈 pinia,看了一下文档,它的使用方法更贴近于 Composition API,对 TypeScript 也更友好,写法上也更简洁,emmm...,香啊!


网络异常,图片无法展示
|


这必须安排啊,于是我开始用 pinia 替换 vuex。


  1. store 文件夹下的所有文件重构
  2. 项目中所有基于 vuex 的状态替换为基于 pinia 的状态


= 获取状态响应式丢失


然后遇到第一个问题,如果要获取某个状态,并进行一些操作,最好不要这么写


import { useSettingStore } from "@/store/setting";
const settingStore = useSettingStore();
const isCollapse = settingStore.isCollapse;
const changeCollapse = () => {
  settingStore.isCollapse = !isCollapse;
};
复制代码


这样直接 const isCollapse = settingStore.isCollapse; 通过 = 赋值拿到的状态是没有响应式的,正确的方式是通过 storeToRefs 进行解构获取,修改后代码如下:


import { storeToRefs } from "pinia";
import { useSettingStore } from "@/store/setting";
const settingStore = useSettingStore();
const { isCollapse } = storeToRefs(settingStore);
const changeCollapse = () => {
  settingStore.setCollapse(!isCollapse.value);
};
复制代码


ps: 修改状态的时候最好还是通过 action 来做。


cdn 加载 Vue 线上环境 pinia 响应式丢失


这个坑真的是如果思路不对,要被坑死。


为了项目更快的加载,我配置了 external 通过 cdn 加载 VueElementPlus,这里也说一下配置过程,方便需要的小伙伴。


// vite.config.js
import { viteExternalsPlugin } from "vite-plugin-externals";
plugins: [
    // external cdn 引入依赖包
    viteExternalsPlugin(
        {
          vue: "Vue",
          "element-plus": "ElementPlus",
        }
    )
]
复制代码


// index.html
<head>
    <meta ...
    <!-- 导入 Vue 3 -->
    <script src="//unpkg.com/vue@next"></script>
    <!-- 导入样式 -->
    <link rel="stylesheet" href="//unpkg.com/element-plus/dist/index.css" />
    <!-- 导入组件库 -->
    <script src="//unpkg.com/element-plus"></script>
    <title>...
<head>
复制代码


这样就完成了,这里用到了 vite-plugin-externals 插件,记得要安装一下。


到了这里,一切都很美好,打包上线吧!


项目部署之后,随便点一点测试下,然后发现当我点击这个按钮控制侧边栏展开收起的时候,


网络异常,图片无法展示
|

网络异常,图片无法展示
|


没有作用?!打开本地服务,点击,比德芙还丝滑好不好!那么问题就出在了线上环境和本地服务的差异。


因为线上环境每次都需要部署,比较麻烦(我是在个人服务器上部署了一套测试,所以不影响真实的线上环境),同时为了对比是不是线上环境的问题(Linux 服务器以及 nginx 配置),我在登录页面获取了 isCollapse 并尝试进行操作,同样,本地服务没有问题,打包,开启 Live Serve,发现本地环境操作也不行,那么就可以确定是打包后的文件出了问题。


因为我项目配置了 cdn 加载 Vue,所以自然想到了这个问题,把 cdn 加载干掉,再次打包,开启 Live Serve,发现本地环境可以了。


到了这里,可以确定配置 cdn 加载后,造成了这个问题。因为实际项目依赖和模块比较多,为了排除干扰,调试更方便,我开了一个新的测试项目(我是之前就有这么一个专门用来测试问题的项目,用来复现和调试实际项目中的问题),首先把 Vue ElementPlus pinia 都搞好,不开启 cdn 加载,本地服务和打包后的本地环境都是 OK 的,然后开启 cdn 加载,本地服务 OK,打包后本地环境 pinia 响应式失效,完美复现。


接下来就是排查具体原因,有两个点:


  1. vite-plugin-externals
  2. pinia


查看 vite-plugin-externalsREADME 可以看到,它只是把依赖库的引入转为 window 下的全局变量,


// 选项
viteExternalsPlugin({
  vue: 'Vue',
}),
// 源代码
import Vue from 'vue'
// 转换后
const Vue = window['Vue']
复制代码


并没有其他什么操作,所以我感觉不是它的问题,排除嫌疑。


那么就剩下 pinia 了,这个时候我打开打包后的 vendor.js 发现里面还是有 Vue 的代码。


网络异常,图片无法展示
|


vue hack 数组


然后我去看了下 pinia 的源码,发现它依赖了 vue-demi 这个库,而 vue-demi 这个库又依赖了 Vue ,而我们配置 external 的插件 vite-plugin-externals 默认是不处理 node_modules 下面的包的,所以我们使用的 Vue 实例和 pinia 绑定的 Vue 实例不是一个实例,所以我们操作 pinia 中的状态在项目中表现为没有响应。


所幸 vite-plugin-externals 提供配置,可以帮我们处理 node_modules 下面的包,所以修改配置如下:


// vite.config.js
import { viteExternalsPlugin } from "vite-plugin-externals";
plugins: [
    // external cdn 引入依赖包
    viteExternalsPlugin(
        {
          vue: "Vue",
          "element-plus": "ElementPlus",
        },
        {
          filter(code, id) {
            // 处理 pinia,解决 cdn 加载 Vue 响应式丢失问题
            if (id.includes("pinia")) {
              return true;
            }
            return false;
          },
        }
]
复制代码


这样 vite-plugin-externals 就会帮我们把 pinia 中依赖的 Vue 也处理成 window['Vue']


再次打包测试,本地环境以及部署线上环境就都 OK 了!


网络异常,图片无法展示
|


2022.3.13 更新

今天搭建新的开发框架遇到一个问题,vite-plugin-externals 之前我用的是 0.0.93 版本,这两天发布了 1.0.9 版本,今天默认安装也是这个版本,结果出现页面刷新后,再操作 pinia 状态,部分状态缓存失败问题,已提 issues,如果大家使用 1.0.0 版本出现问题,可以尝试使用 0.0.93 版本。


如有任何问题或建议,欢迎留言讨论!

相关文章
|
SQL 关系型数据库 MySQL
Apache Hudi在信息服务行业构建流批一体的实践
Apache Hudi在信息服务行业构建流批一体的实践
657 2
|
小程序 定位技术
微信小程序:map地图自动缩放自适应大小
微信小程序:map地图自动缩放自适应大小
1355 0
|
SQL
SQL Server判断某个字段是否包含中文/英文字符/数字
原文:SQL Server判断某个字段是否包含中文/英文字符/数字 因最近在清理系统中的脏数据,需要查询某个字段是否包含中文/英文字符/数字的数据, 比较简单,仅以此篇博客做一个简单总结,方便以后查阅。
5238 0
|
安全 搜索推荐 网络安全
Windows操作系统的演变与未来趋势####
本文将深入探讨Windows操作系统从诞生至今的发展历程,分析其关键版本的技术创新、市场影响及用户反馈。同时,结合当前科技趋势,预测Windows系统的未来发展方向,包括智能化、云集成、安全性提升等方面的可能性。 ####
|
数据采集 数据安全/隐私保护 Python
【Python】已解决:urllib.error.HTTPError: HTTP Error 403: Forbidden
通过上述方法,可以有效解决 `urllib.error.HTTPError: HTTP Error 403: Forbidden` 错误。具体选择哪种方法取决于服务器对请求的限制。通常情况下,添加用户代理和模拟浏览器请求是最常见且有效的解决方案。
1018 10
|
SQL Oracle 关系型数据库
深入解析 NOW() 与 CURRENT_DATE() 的区别
【8月更文挑战第31天】
1076 1
|
缓存 移动开发 JavaScript
WKWebView对网页和js,css,png等资源文件的缓存机制及如何刷新缓存
WKWebView对网页和js,css,png等资源文件的缓存机制及如何刷新缓存
1231 1
|
移动开发 小程序 数据可视化
DIY可视化导出源码整合uniapp环境搭建+调试+运行发布
DIY可视化导出源码整合uniapp环境搭建+调试+运行发布
699 0
|
安全 网络协议 Java
log4j-CVE-2021-44228-vulhub复现
log4j-CVE-2021-44228-vulhub复现
799 0
|
存储 算法 前端开发
swap去中心化交易所系统丨swap去中心化交易所系统开发技术详细丨swap去中心化交易所开发案例及源码
 Uniswap去中心化exchange是基于以太坊的代币交换协议,基于兑换池(即Capital pool),而用户在Uniswap中交易的价格则由这个Capital pool中的代币比例和算法来决定。
1038 0