Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >用 Vue3 就该有不用 pinia 的自信

用 Vue3 就该有不用 pinia 的自信

作者头像
用户6901603
发布于 2024-07-25 08:12:53
发布于 2024-07-25 08:12:53
20600
代码可运行
举报
文章被收录于专栏:不知非攻不知非攻
运行总次数:0
代码可运行

首先说一下观点。

不管是用 React,还是用 Vue3,实际上大多数项目完全都可以不用全局状态管理库。不过在 React 中,要做到这样的事情,需要非常强的综合能力,在 Vue3 中,要做到这个事情更为简单。

但是毕竟也是需要一点点技术含量的,全局状态管理是一个非常好的解决问题的思路,他足够的简单粗暴,能够解决几乎所有的状态问题。因此,这至少是一个在功能上不会出纰漏的方案。

但是,我想说的是,用 Vue3 就应该有不用 pinia 的自信。 当然我也知道,部分 Vue3 的使用者,并不能快速接受这个事情。


全局状态管理的弊端

全局状态管理是一种非常好的架构思路,他足够简单粗暴。你只需要把数据放在全局状态中,就可以不用担心任何组件拆分的问题。哪怕你的组件拆得再烂再不合理,也对功能的实现没有任何影响。最终的结果就是,大多数的项目,耦合严重。

当然,如果你对项目解耦的标准并不是那么看重,那么我们可能观念很难达成一致。毕竟几千行几万行一个组件的代码,也大行其道,观念不一也很正常。

有的时候,项目写久了之后,你甚至都不知道自己在这个页面定义的状态,到底别的页面用了没用。一旦涉及到 bug 修复、旧功能维护、项目迁移、重构,就极有可能会出现很多意料之外的困难。因此,我觉得,在不用或者尽量少用全局状态管理的基础之下,如何把自己的项目的理顺,实际上是一名优秀前端架构师应该追求的一个方向。

大多数时候,我们都应该遵循单一原则,每个页面,只维护自己相关的状态,并且也应该尽量想办法让这些状态变成页面私有状态,避免共享

当然,我只是提一个建议往这个方向去思考,并不是说,你就应该马上要这样做,毕竟每个人的项目都有各自的历史背景,难度和工作量各不相同。我只是告诉你一个结论,无全局状态管理完全足够应对大型的、复杂的项目,因为,我一直在项目中践行这个事情,这是长期实践之后的结论。

!事实上,全局状态管理方案在有的复杂 B 端项目中还会带来内存占用过大的隐患,我们需要单独的去思考内存释放的问题。但是这一般是在客户是医院、国企、政府单位时才会经常遇到的情况

我的原则就是:能不用就不用


Vue3 中,更容易做到弃用全局状态管理

在 React 中,状态私有这个事情要做得更好一些。我们无法把一个 state 定义到函数组件外部去。因此,从我个人的观点来看,这其实是一个优点。但是很多人却因为这样的限制感觉不自在,把他当成一个缺点。

甚至有的新型框架还会把 React 不支持状态定义在组件之外去特地贬低 React,并以此为卖点来抬高自己 ...

和 React 不同的是,在 Vue3 中,我们可以很轻易的把状态定义到组件之外去。并且还能在此基础之上,保持数据与 UI 的响应关系。

我们只需要单独起一个 ts 文件就可以做到这个事情

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import {ref} from 'vue'

export const count = ref(20)

export function increment() {
  count.value++
}

这其实是利用了闭包的特性做到了状态共享。它和全局状态管理的作用几乎是一模一样的。因此,在每个人的个人能力范围以内,大家可以在不得不用全局状态时,小范围的使用这种方式。

而 React 则还需要做一层额外的封装。


不使用 pinia,你损失了什么

首先,我们必要明确的是,我们应该优先把数据和状态,管理到函数组件之中,让他保持私有性。

全局状态管理应该作为一个兜底的方案,让它成为最后的选择。

因此,在这种小概率的范围之内,如果不使用 pinia,可能会存在的风险包括

  • 1、ssr 时利用闭包共享状态可能会出现意外的情况
  • 2、调试时无法追踪状态的变化
  • 3、调试时无法获得热更新的能力
  • 4、编写测试代码变得困难

首先,从大的范围来说,本身我们在全局状态管理中要存储的数据就应该非常非常少。这些影响就算一点都不解决,他其实也已经被降到了最低。因此这些损失也并不是不能接受。

我们再来一条一条的解读一下这些损失。

针对第一条,服务端渲染的理解。首先我们应该明确一个标准,那就是与客户端相比,服务端渲染的页面之间,更应该尽量避免共享可变状态。每一个服务端渲染出来的页面应该是单独的页面实例。在这个理念的基础之上去编写代码,你会发现你很难出问题。

第二条,我们要考虑的一个问题就是,我们在 debug 的时候,真的有很依赖状态追踪吗?console.log 才是调试方案中的最佳实践!

第三条,由于在函数组件之外声明响应式数据,因此这些数据在初始化时就被执行了,因此很难在更新时得到执行的时机,所以无法获得热更新的能力。但是由于我们只应该把小部分逻辑存放于此,因此这基本上不会对页面调试造成任何困扰。况且,当数据变得复杂时,hot reload 机制也并不那么好用,有的时候还不如重新刷新页面执行一次。结合 console.log 更容易发现问题所在

第四条,我的观点是,极小部分固定的共享状态,完全可以不需要编写测试代码,他们更多的只是基础的写入和读取的逻辑。例如登录状态,我们可以给登录逻辑单独编写测试用例即可。当然,大多数的团队,连一行测试代码也不行

很多团队确实也没太大的必要


总结

思考如何在项目中去全局状态管理,有利于帮助我们思考页面和组件的解耦问题,对我们的抽象能力是一个很好的训练机会。并且在思考这个问题的过程中,我们明确了自己可能会得到什么,以及会承担什么代价,并在这个充分的考虑过程后做出的决定。

我一直比较提倡的是不要在项目中使用全局状态管理工具。而 vue3 由于可以方便的把响应式状态声明在函数组件之外,用这种方式来兜底,他能够更容易平滑的做到这个事情。


一个区别

当我们使用自定义 hook 的方式来创建响应式状态时,和直接把状态声明在函数组件之外是有很大区别的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 自定义hook
function useCounter() {
  const count = ref(20)

  function increment() {
    count.value++
  }
  return {count, useCounter}
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 单独的模块
export const count = ref(20)

export function increment() {
  count.value++
}

这里的区别就是在于,每次我们在不同的组件中执行自定义 hook useCounter,函数的上下文都是不同的。因此,在函数中执行 useCounter() 所得到的状态都是函数组件内部私有的。

但是第二种单独的模块的方式,这是一个公有的方案。当我们在别的模块中引入他们并使用时,实际上两个模块此时会构成一个闭包环境,从而让数据得到共享。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import {count, increment} from './useCounter'

我们在思考这个方案时,要注意区分这两种场景。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-07-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 这波能反杀 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
VUE基础讲解
回调地狱:上一个接口还没有走完,下一个接口已经开始了,但是下一个接口需要上一个接口的数据
叶秋学长
2022/07/17
3640
VUE基础讲解
收藏好了,JS开发须知道的41个小技巧
链接:https://juejin.im/post/6854573212890562573
coder_koala
2020/11/10
5740
收藏好了,JS开发须知道的41个小技巧
es6 - spreed & rest 【... 扩展运算符】
往apply的第二个参数处传入一个数组,数组在apply内部就会被一一展开成一个参数列表,log接收到的就是这个展开的参数列表,
xing.org1^
2019/05/14
9310
es6 - spreed & rest 【... 扩展运算符】
二、ES6新语法
图中可对比看出,如果用var声明,在循环外部还是可以使用i变量;但用let声明变量,循环外部不可以使用n变量
Dreamy.TZK
2020/07/03
4030
小邵教你玩转ES6(一)-let,const和解构赋值
这篇文章主要让你学会工作当中常用的es6技巧,以及扩展如实现数据双向绑定,class用es5如何实现、如何给伪数组添加迭代器等等。
前端迷
2019/12/03
6520
小结ES6基本知识点(一)
ES6初学者,通过阅读本文可对ES6知识点有个大体的概念,强烈建议阅读阮一峰大大的ES6入门。
前端林子
2019/02/24
2.9K0
小结ES6基本知识点(一)
ES6技术
JavaScript之前是LiveScript,具体的资料,大家自己查一下百度。网景公司的语言,这个公司为了把自己的公司语言,走出美国,迈向世界。把自己的语言提交给了ECMA。
张哥编程
2024/12/19
1140
ES6技术
JS开发必须知道的41个技巧【持续更新】
JS是前端的核心,但有些使用技巧你还不一定知道; 本文梳理了JS的41个技巧,帮助大家提高JS的使用技巧; 文章有点长,可以clone下源码,直接撸,源码地址请戳全部源码,原创不易,欢迎star; 序列文章: Vue 开发必须知道的 36 个技巧 React 开发必须知道的 34 个技巧
火狼1
2020/07/21
8440
个人小结--javascript实用技巧和写法建议
从大学到现在,接触前端已经有几年了,感想方面,就是对于程序员而言,想要提高自己的技术水平和编写易于阅读和维护的代码,我觉得不能每天都是平庸的写代码,更要去推敲,去摸索和优化代码,总结当中的技巧,积极听取别人的建议,这样自己的技术水平会提高的更快。那么今天,我在这里就分享一下关于javascript方面的写作的实用技巧和建议,这些技巧和建议是我平常在开发项目上会用到的,希望能让大家学到知识,更希望能起到一个交流意见的作用,也就是说大家有什么好的技巧或者建议,欢迎分享,或者觉得我的想法存在什么问题,欢迎指出!
守候i
2018/08/22
5540
个人小结--javascript实用技巧和写法建议
JavaScript ES6  让我们写得少,做得多
JavaScript ES6 带来了新的语法和新的强大功能,使您的代码更现代,更易读。它允许您编写更少的代码并执行更多操作。 ES6 向我们介绍了许多强大的功能,如箭头函数,模板字符串,对象结构,模块等,让我们来看看。
桃翁
2018/10/18
8490
ES6归纳总结
let 的特点 let声明的变量只在所处的块级有效(块级作用域不受外部影响具有暂时死区特性),也就是说在{ }内声明的变量,只在 { }中可以使用,在其他地方不能使用。 防止循环变量,变成全局变量。 for(var i=0;i<3;i++){ } console.log(i);// 输出 3 for(let i=0;i<3;i++){ } console.log(i);/// 未定义 不存在变量提升 具有暂时死区 var num = 10; if (true){ console.log(num); //
用户4344670
2020/02/24
6440
JS 中使用扩展运算符的10种方法,好家伙,点个赞呗!
最近开源了一个 Vue 组件,还不够完善,欢迎大家来一起完善它,也希望大家能给个 star 支持一下,谢谢各位了。
前端小智@大迁世界
2021/02/22
1K0
JS 中使用扩展运算符的10种方法,好家伙,点个赞呗!
盘盘项目中你常用到的数组API
数组在业务中是一个非常高频的API,在业务中基本都有用它,必不可少,本文是笔者一篇关于数组常用API的总结,希望看完在项目中有所帮助。
Maic
2022/12/21
5810
盘盘项目中你常用到的数组API
JS基础第二课(函数、对象篇)
JavaScript中的重要功能,是一段代码的集合,这段代码可以在不同地方调用,从而提高JavaScript代码的复用性
申小兮
2023/04/12
5630
JS基础第二课(函数、对象篇)
ES6新增特性
在ES6新特性中,增加的两个声明变量和常量的方法,let用于声明变量,const用于声明常量。
青梅煮码
2023/01/31
7570
重读 ES6 标准入门(第3版)
仅将自己的理解做整理、归类并结合实际遇到的问题做记录,更推荐阅读 ECMAScript 6 入门。
掘金安东尼
2024/01/28
1700
ES6常用知识点小结
ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准。
Krry
2018/09/10
9030
ES6常用知识点小结
ES6
在cmd命令窗口初始化项目-y代表全部默认同意,就不用一次次按回车了。命令执行完成后,会在项目根目录下生产package.json文件。
楠楠
2018/09/11
2.8K0
常用utils
数组最大最小值 function min(nums) { var res = nums[0] for (var i = 0; i < nums.length; i++) { if (res > nums[i]) { res = nums[i] } } return res } function max(nums) { var res = nums[0] for (var i = 0; i < nums.l
hss
2022/02/25
2650
浅学前端:JavaScript篇(二)
现在希望当某个属性是 nullish 时,短路并返回 undefined,可以用 ?.
传说之下的花儿
2023/11/09
1920
浅学前端:JavaScript篇(二)
相关推荐
VUE基础讲解
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验