Vue 进阶系列丨Pinia 的基本使用
Vue 进阶系列教程将在本号持续发布,一起查漏补缺学个痛快!若您有遇到其它相关问题,非常欢迎在评论中留言讨论,达到帮助更多人的目的。若感本文对您有所帮助请点个赞吧!
2013年7月28日,尤雨溪第一次在 GItHub 上为 Vue.js 提交代码;2015年10月26日,Vue.js 1.0.0版本发布;2016年10月1日,Vue.js 2.0发布。
最早的 Vue.js 只做视图层,没有路由, 没有状态管理,也没有官方的构建工具,只有一个库,放到网页里就可以直接用了。
后来,Vue.js 慢慢开始加入了一些官方的辅助工具,比如路由(Router)、状态管理方案(Vuex)和构建工具(Vue-cli)等。此时,Vue.js 的定位是:The Progressive Framework。翻译成中文,就是渐进式框架。
Vue.js2.0 引入了很多特性,比如虚拟 DOM,支持 JSX 和 TypeScript,支持流式服务端渲染,提供了跨平台的能力等。Vue.js 在国内的用户有阿里巴巴、百度、腾讯、新浪、网易、滴滴出行、360、美团等等。
Vue 已是一名前端工程师必备的技能,现在就让我们开始深入学习 Vue.js 内部的核心技术原理吧!
什么是 Pinia
Pinia 是 vue 官方成员在2019年11月重新设计的一个状态存储库,它允许你跨组件/页面共享状态,并且是响应式的,类似于 vuex。现在 vuex 已经更新到4.x版本了,你可以认为 pinia 是作为 vuex@5.x 的一种存在。
与vuex相比,有以下几点不同:
没有 mutations,只有 actions。
完美支持TS,相比于vuex,支持 ts 还需要做一些额外的工作,具体内容请移步Vue 进阶系列丨Vuex+TS 代码提示
没有命名空间模块,pinia的store是扁平化结构,你创建的多个store都是相互隔离的,没有嵌套关系。
不再需要注入、导入函数。
创建项目
npm init vite@latest
引入 pinia
npm install pinia
// main.ts
import { createPinia } from 'pinia'
app.use(createPinia())
定义一个store
通过 defineStore 来定义 store,它需要一个唯一的名称,作为第一个参数传入:
// @/store/firstStore.js
import { defineStore } from 'pinia'
// 定义并导出容器,第一个参数是容器id,必须唯一,用来将所有的容器
// 挂载到根容器上
export const useFirstStore = defineStore('myStore',{
// 定义state,用来存储状态的
state:()=>{
return {}
},
// 定义getters,类似于computed,具有缓存g功能
getters:{},
// 定义actions,类似于methods,用来修改state,做一些业务逻辑
actions:{}
})
使用刚刚定义的 store:
import { useFirstStore } from '@/store/firstStore.js'
<script setup lang='ts'>
// 拿到store
const firstStore = useFirstStore()
</script>
state
定义 state:
import { defineStore } from 'pinia'
// 挂载到根容器上
export const useFirstStore = defineStore('myStore',{
// 定义state,用来存储状态的
state:()=>{
return {
count:0,
arr:[1,2,3]
}
},
// 定义getters,类似于computed,具有缓存g功能
getters:{},
// 定义actions,类似于methods,用来修改state,做一些业务逻辑
actions:{}
})
使用 state:
import { useFirstStore } from '@/store/firstStore.js'
<template>
{{firstStore.count}}
</template>
<script setup lang='ts'>
// 拿到store
const firstStore = useFirstStore()
console.log(firstStore.count) // 0
</script>
注意,将 store 解构之后,就不是响应式的了,如果想要解构,则需要使用 storeToRefs 函数包裹。
原因很简单,store 其实就是一个 reactive 对象,当我们解构的时候,就不是响应式数据了,就像 vue3 中一样,需要使用 toRefs 函数。
import { useFirstStore } from '@/store/firstStore.js'
import { storeToRefs } from 'pinia
<template>
{{count}}
{{arr}}
</template>
<script setup lang='ts'>
// 拿到store
const firstStore = useFirstStore()
// 这样就不是响应式的了,当我们修改count的值的时候,页面不会响应式变化
const { count,arr } = firstStore // 错误的做法
const { count,arr } = storeToRefs(firstStore) // 正确的做法
</script>
修改 state:
import { useFirstStore } from '@/store/firstStore.js'
<template>
{{count}}
</template>
<script setup lang='ts'>
// 拿到store
const firstStore = useFirstStore()
// 方式一,直接修改
firstStore.count += 1
// 方式二,如果修改多个数据,可以使用$patch批量修改
firstStore.$patch({
count:firstStore.count + 1,
arr:[...firstStore.arr,4]
})
// 方式三: $patch一个函数
firstStore.$patch(state=>{
state.count++
state.arr.push(4)
})
// 方式四,调用actions
firstStore.changeCount()
// 方式五,替换整个state
firstStore.$state={
count:2,
arr:[1,2,3,4]
}
// 方式六:重置state
firstStore.$reset()
</script>
Getters
定义 getters:
import { defineStore } from 'pinia'
// 挂载到根容器上
export const useFirstStore = defineStore('myStore',{
// 定义state,用来存储状态的
state:()=>{
return {
count:0,
arr:[1,2,3]
}
},
// 定义getters,类似于computed,具有缓存g功能
getters:{
// 依赖state
doubleCount(state){
return state.count *2
},
// 依赖其他的getters, :number 是指定返回值类型为number类型
otherCount():number{
return this.doubleCount + 1
}
},
// 定义actions,类似于methods,用来修改state,做一些业务逻辑
actions:{}
})
获取 getters:
import { useFirstStore } from '@/store/firstStore.js'
<template>
{{firstStore.doubleCount}}
{{firstStore.otherCount}}
</template>
<script setup lang='ts'>
// 拿到store
const firstStore = useFirstStore()
console.log(firstStore.doubleCount)
console.log(firstStore.otherCount)
</script>
Actions
定义 actions:
import { defineStore } from 'pinia'
// 挂载到根容器上
export const useFirstStore = defineStore('myStore',{
// 定义state,用来存储状态的
state:()=>{
return {
count:0,
arr:[1,2,3]
}
},
// 定义getters,类似于computed,具有缓存g功能
getters:{
// 依赖state
doubleCount(state){
return state.count *2
},
// 依赖其他的getters, :number 是指定返回值类型为number类型
otherCount():number{
return this.doubleCount + 1
}
},
// 定义actions,类似于methods,用来修改state,做一些业务逻辑
actions:{
// 接收一个参数num,参数的类型是number类型
addCount(num:number){
// 通过this获取state中的数据,就像vue2的optionsApi一样
this.count+=num
}
}
})
调用 actions:
import { useFirstStore } from '@/store/firstStore.js'
<template>
{{firstStore.count}}
</template>
<script setup lang='ts'>
// 拿到store
const firstStore = useFirstStore()
firstStore.addCount(10)
</script>
至此,pinia 在 vue3 中的简单使用到此就结束了,还是很推荐大家去使用pinia 的,尤其是在TS项目里。现在pinia已经被官方接管了,而且它也是 vue官方成员开发的。这里是 pinia 官网:https://pinia.vuejs.org/ ,大家也可以去官网深入学习。
Vue 进阶系列教程将在本号持续发布,一起查漏补缺学个痛快!若您有遇到其它相关问题,非常欢迎在评论中留言讨论,达到帮助更多人的目的。若感本文对您有所帮助请点个赞吧!
叶阳辉
HFun 前端攻城狮
往期精彩:
Vue 进阶系列丨Object 的变化侦测
Vue 进阶系列丨Array 的变化侦测
Vue 进阶系列丨虚拟DOM和VNode
Vue 进阶系列丨Patch 和模板编译
Vue 进阶系列丨事件相关的实例方法
Vue 进阶系列丨生命周期相关的实例方法
Vue 进阶系列丨生命周期
Vue 进阶系列丨自定义指令
Vue 进阶系列丨最佳实践
Vue 进阶系列丨Mixin 混入
Vue 进阶系列丨权限控制 addRoute()
Vue 进阶系列丨插槽
Vue 进阶系列丨npm发布vue组件
Vue 进阶系列丨Vuex+TS 代码提示
Vue 进阶系列丨自定义指令实现按钮权限功能
来源:HFun TM