Vue3 项目你需要用 Pinia 替代 Vuex
Pinia 替代 Vuex4?你在说什么?此时你心中肯定会产生很多疑问,例如 Pinia 是什么?Pinia 有什么优势?诸如此类的问题,你给笔者五分钟,笔者给你一个满意的答案!
去年10月的一场前端早早聊中,尤大下场给大家答疑,其中有个问题是 pinia 会替代 vuex 吗?
很大概率,都是 core team 成员,讨论结果未来形态会很像 pinia,新东西都写在 pinia 里,如果开发一个新项目,如果使用 ts,推荐使用 pinia。
我相信尤大推荐胜过笔者的千言万语~~~
But,为了收获你宝贵的一个赞,笔者还是做足了准备,请给笔者 5 分钟,我们一起探索 Pinia~~~
Pinia 介绍和五大优势
Vue3 自 2月7号 设置为默认版本后,预示着 Vue3 的开发生态已经完备,项目中可以安心的使用 Vue3 开发项目。Pinia 则是尤大推荐配合 Vue3 使用的状态管理工具,而且 Pinia 的开发团队也是 Vue 的核心成员,并且下一代 Vuex5 很多提案都包括了 Pinia 的几个优势。
五大优势
- 可以对 Vue2 和 Vue3 做到很好的支持
- 完美支持 TypeScript
- 无需像 Vuex 4 自定义复杂的类型来支持 typescript,天生具备完美的类型推断
- 更加简洁的语法,完美支持 Vue3 的 Composition api
- 解决了代码反复横跳的问题,Pinia 与 Vue devtools 挂钩,不会影响 Vue 3 开发体验
- 抛弃了 Mutations 的操作,只有 state、getters 和 actions
- 极大的简化了状态管理库的使用,让代码编写更加容易直观
- 模块化设计,无嵌套结构,体积很小不超过 1kb
- 你引入的每一个 store 在打包时都可以自动拆分,且可以交叉组合使用 store
如果你说这五点有点太多了,记不住。可以简单总结 Pinia 的优势就是,更加简洁的语法,完美支持 Vue3 的 Composition api 和对 TypeScript 的完美支持。
Pinia 的安装与使用
纸上得来终觉浅,绝知此事要躬行。笔者建议学习时,手动敲印象会更深刻哦~~~
使用示例
安装环境
// 安装 vite 项目
npm init vite@latest
// 安装 Pinia 包 当前版本 2.0.11
npm install pinia@latest
注册 Pinia
// main.ts 注册 pinia
import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia';
const pinia = createPinia()
createApp(App).use(pinia).mount('#app')
新建仓库
// src/store/index.ts
import { defineStore } from 'pinia';
export const mainStore = defineStore('main', {
state: () => {
return {
helloWorld: 'hello world!'
}
},
getters: {},
actions: {}
});
// composition API 写法
export const mainStore = defineStore('main', () => {
const helloWorld = ref('hello world!')
return { helloWorld }
})
- defineStore() 定义一个仓库。
- defineStore( )方法的第一个参数:相当于为容器起一个名字。注意:这里的名字必须唯一,不能重复。这个是官方特别说明的一个事情。
- defineStore( )方法的第二个参数:可以简单理解为一个配置对象,里边是对容器仓库的配置说明。当然这种说明是以对象的形式。
- state 属性:用来存储全局的状态的,这里边定义的,就可以是为 SPA 里全局的状态了。
- getters 属性:用来监视或者说是计算状态的变化的,有缓存的功能。
- actions 属性:对 state 里数据变化的业务逻辑,需求不同,编写逻辑不同。说白了就是修改 state 全局状态数据的。
使用
<template>
<h2>{{ store.helloWorld }}</h2>
<h2>{{ helloWorld }}</h2>
</template>
<script lang='ts' setup>
import { mainStore } from '../store/index';
import { storeToRefs } from 'pinia';
// 执行这个实例
const store = mainStore()
// 如果是解构 需要使用 storeToRefs 不然就会失去响应式
const { helloWorld } = storeToRefs(store)
</script>
getters
如果你在获取 State 的值时作一些处理,比如处理手机号中间四位,那么就可以使用 getters,并且 getters 是有缓存特性的。
// store/index.ts
export const mainStore = defineStore('main', {
state: () => {
return {
phoneNumber: 18797890000
}
},
getters: {
phoneHidden(state) {
console.log('PhoneHidden被调用了');
return state.phoneNumber.toString().replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2')
}
},
actions: {
...
}
});
// 使用 => <h2>{{ store.phoneHidden }}</h2> 这样界面上显示的数据就是 187****0000
修改状态数据的方式
直接修改
<h2>{{ store.count }}</h2>
// 点击按钮就能更新
const handleClick = function () {
store.count++
}
使用 $patch
如果是多条数据,推荐使用$patch,$patch的方式是经过优化的,会加快修改速度,对程序的性能有很大的好处。所以如果你是多条数据同时更新状态数据,推荐使用 $patch 方式更新。
const handleClick = function () {
store.$patch({
count: store.count + 1,
helloWorld: store.helloWorld === 'Pinia' ? 'Vue3' : 'Pinia'
})
}
使用 action
在 actions 中写好逻辑 再调用 actions
const handleClick = function () {
store.changeState()
}
// store/index
export const mainStore = defineStore('main', {
state: () => {
return {
helloWorld: 'Pinia',
count: 0,
phoneNumber: 18797894671
}
},
getters: {
// 在获取 State 的值时作一些处理
// Getters 是有缓存特性的
phoneHidden(state) {
console.log('PhoneHidden被调用了');
return state.phoneNumber.toString().replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2')
}
},
actions: {
// 不能使用箭头函数 因为需要使用 this
// 箭头函数绑定的是 外部的 this
changeState() {
this.count++
this.helloWorld = 'Leiloloaa'
},
}
});
store 的相互调用
项目中可能有多个 store,pinia 支持相互间的调用
// 在 store 文件夹下 新建 goods.ts
import { defineStore } from 'pinia';
export const goodsStore = defineStore('goods', {
state: () => {
return {
list: ['vue3', 'pinia', 'vuex']
}
}
})
// store/index.ts
import { defineStore } from 'pinia';
import { goodsStore } from './goods';
export const mainStore = defineStore('main', {
state: () => {
return {}
},
getters: {},
actions: {
getList() {
console.log(goodsStore().list);
}
}
});
ENDING
使用 Pinia 之后,Vuex 就别再来了~~~ 希望本文能够帮助到屏幕面前你,不赶时间的话,可以给笔者点个赞吗?手动比心~
阮一峰推荐的 Vue3 源码学习利器 mini-vue,我已经上车,若是想学习 Vue3 源码课程,可扫描下方二维码咨询!
学习 mini-vue 你能得到什么?
- 方便阅读 Vue3 源码
- 命名相同,实现方式相同
- TDD 单元测试
- 重构代码、位运算等
- 后续的分享学习服务
- 社群解答,同学分享 等等 好处