Vue 进阶系列丨Pinia 的基本使用

2年前 (2022) 程序员胖胖胖虎阿
367 0 0

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 进阶系列教程将在本号持续发布,一起查漏补缺学个痛快!若您有遇到其它相关问题,非常欢迎在评论中留言讨论,达到帮助更多人的目的。若感本文对您有所帮助请点个赞吧!

Vue 进阶系列丨Pinia 的基本使用

叶阳辉

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

版权声明:程序员胖胖胖虎阿 发表于 2022年9月2日 上午8:48。
转载请注明:Vue 进阶系列丨Pinia 的基本使用 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...