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 进阶系列丨自定义指令实现按钮权限功能