• Pinia使用笔记


    简介

    Pinia是一个全新的Vue状态管理库,由 Vue.js团队成员开发。

    对比vuex

    1. pinia的模块更像一个hooks,不需要嵌套,模块之间可以互相引用,让代码组织更灵活
    2. 符合Vue3 的 Composition api的风格,可以直接结合vue3的API定义状态
    3. 没有mutations,只有 state、getters、actions,devtools同样可以追踪到状态的修改
    4. vue2和vue3都可以支持
    5. TypeScript类型推断

    安装

    1. yarn add pinia
    2. # 或者使用 npm
    3. npm install pinia
    4. 复制代码

    完整示例

    首先需要在main.ts引入

    1. import { createApp } from 'vue'
    2. import { createPinia } from 'pinia'
    3. const app = createApp(App)
    4. app.use(createPinia())
    5. app.mount('#app')
    6. 复制代码

    定义状态

    defineStore函数用来定义一个状态,返回一个使用状态的函数。

    我们把状态定义在在/src/store/index.ts文件内,当然也可以定义在其他文件内,并且defineStore可以定义多个状态集合

    1. import { defineStore } from 'pinia'
    2. // useStore 可以是 useUser、useCart 之类的任何东西
    3. export const useCountStore = defineStore('count', {
    4. // state:定义状态
    5.    state: ()=>({
    6.        count: 0
    7.   }),
    8. // getters:与vuex一致,类似于computer
    9.    getters: {
    10.        dbCount:(state)=>state.count*2
    11.   },
    12. // actions:与vuex一致,用于修改状态
    13.    actions: {
    14.        countPlus() {
    15.            this.count++
    16.       }
    17.        
    18.   }
    19. })
    20. 复制代码

    defineStore第一个参数是应用程序中 store 的唯一 id,第二个参数是一个选项的对象,与Vuex类似不过没有Mutation字段

    使用状态

    调用useStore方法,返回store实例

    1. <template>
    2.  <div class='home'>
    3.    <div>{{countStore.count}}</div>
    4.    <button @click="countPlus">count++</button>
    5.  </div>
    6. </template>
    7. <script setup lang="ts">
    8. import {useCountStore} from "./useStore";
    9. const countStore = useCountStore()
    10. // 通过countStore可以直接访问到state、getters、actions中定义的状态和方法
    11. countStore.count
    12. countStore.dbCount
    13. countStore.countPlus()
    14. function countPlus(){
    15.  // 可以直接修改 count
    16.  countStore.count++
    17.  // 也可以通过$state替换整个状态
    18.  countStore.$state = {count: countStore.count+1}
    19.  // 使用$patch修改状态
    20.  countStore.$patch({
    21.    count: countStore.count+1
    22. })
    23.  // 调用actions中的方法
    24.  countStore.countPlus()
    25. }
    26. </script>
    27. 复制代码

    defineStore

    使用配置定义状态

    State

    定义状态

    1. export const useCountStore = defineStore('count', {
    2.    state: ()=>({
    3.        count: 0
    4.   })
    5. })
    6. 复制代码

    访问/修改state

    1. const countStore = useCountStore()
    2. // 访问
    3. countStore.count
    4. countStore.$state.count
    5. // 可以直接修改 count
    6. countStore.count++
    7. // 也可以通过$state替换整个状态
    8. countStore.$state = {count: countStore.count+1}
    9. // 使用$patch修改状态
    10. countStore.$patch({
    11.  count: countStore.count+1
    12. })
    13. 复制代码

    Getters

    计算属性一样,您可以组合多个 getter。 通过 this 访问任何其他 getter。

    1. export const useCountStore = defineStore('count', {
    2.    state: ()=>({
    3.        count: 0
    4.   }),
    5.    getters: {
    6.        // 回调函数的参数为state
    7.        dbCount:(state)=>state.count*2,
    8.        // this为该store实例,可以访问到其他的getters
    9.        doubleCountPlusOne() {
    10.          return this.doubleCount + 1
    11.       }
    12.   }
    13. })
    14. 复制代码

    getter传递参数

    1. export const useCountStore = defineStore('count', {
    2.    state: ()=>({
    3.        count: 0
    4.   }),
    5.    getters: {
    6.     // getters返回一个函数,并接受一个参数
    7.        countFormat: (state) => {
    8.          return (fmt) => state.count+fmt
    9.       },
    10.   }
    11. })
    12. 复制代码

    访问其他 Store 的 getter

    1. export const useUserStore = defineStore('user', {
    2.    state: ()=>({
    3.        name: 'yxx'
    4.   }),
    5.    getters: {
    6.        countFormat: (state) => {
    7.          return (fmt) => state.count+fmt
    8.       },
    9.   }
    10. })
    11. export const useCountStore = defineStore('count', {
    12.    state: ()=>({
    13.        count: 0
    14.   }),
    15.    getters: {
    16.     // getters返回一个函数,并接受一个参数
    17.        userCount: (state) => {
    18.          const userStore = useUserStore()
    19.          return `${userStore.name}写了${state.count}个bug`
    20.       },
    21.   }
    22. })
    23. 复制代码

    访问getters

    1. const countStore = useCountStore()
    2. countStore.dbCount
    3. countStore.doubleCountPlusOne
    4. countStore.countFormat('个')
    5. countStore.userCount
    6. 复制代码

    Actions

    Actions 相当于组件中的 methods。 可以使用 defineStore() 中的 actions 属性定义

    1. export const useCountStore = defineStore('count', {
    2.    state: ()=>({
    3.        count: 0
    4.   }),
    5.    actions: {
    6.      // 与getters一样,可以通过this访问该store实例
    7.      countPlus() {
    8.        this.count++
    9.     },
    10.      // actions 可以是异步的
    11.      async asyncCountPlus(){
    12.        const res = await axios.get('xxxx')
    13.        this.count = res.data
    14.     }
    15.        
    16.   }
    17. })
    18. 复制代码

    访问其他 Store 的 actions

    1. export const useUserStore = defineStore('user', {
    2.    state: ()=>({
    3.        name: 'yxx'
    4.   }),
    5.    actions: {
    6.        setName: () => {
    7.          this.name = 'yxx'
    8.       },
    9.   }
    10. })
    11. export const useCountStore = defineStore('count', {
    12.    state: ()=>({
    13.        count: 0
    14.   }),
    15.    actions: {
    16.        setUserName: (state) => {
    17.          const userStore = useUserStore()
    18.          userStore.setName()
    19.       },
    20.   }
    21. })
    22. 复制代码

    访问actions

    1. const countStore = useCountStore()
    2. countStore.countPlus()
    3. countStore.asyncCountPlus()
    4. countStore.setUserName()
    5. 复制代码

    使用组合式API语法定义状态

    defineStore第二个参数也可以接收一个函数,函数可以返回一个响应式的变量和它的计算属性、修改方法等

    1. import {defineStore} from "pinia";
    2. import {ref, computed} from "vue";
    3. export const useCountStore = defineStore('count', ()=>{
    4.    const count = ref(0)
    5.    const dbCount = computed(()=>count.value*2)
    6.    const userInfo = reactive({
    7.        name: 'yxx',
    8.        age: 12
    9.   })
    10.    function countPlus(){
    11.        count.value++
    12.   }
    13.    return {count, dbCount, userInfo, countPlus}
    14. })
    15. 复制代码

    这种方法与第一种方法定义状态所返回的实例没有区别,访问属性和方法的方式也没有变化

    使用ref或reactive定义的响应式变量等同于state中的状态

    使用computed定义的计算属性等同于getters中的内容

    return出来的其他方法等同于actions中的方法

    1. <template>
    2.  <div class="">
    3.    <div>count: {{countStore.count}}</div>
    4.    <div>dbCount: {{countStore.dbCount}}</div>
    5.    <button @click="butClick">count++</button>
    6.  </div>
    7. </template>
    8. <script setup lang="ts">
    9. import {useCountStore} from "./useStore";
    10. const countStore = useCountStore()
    11. // 访问状态
    12. countStore.count
    13. // 或者
    14. countStore.$state.count
    15. // 访问计算属性  
    16. countStore.dbCount
    17. function butClick(){
    18.  // 访问方法
    19.  countStore.countPlus()
    20. }
    21. </script>
    22. 复制代码

    store实例属性/方法

    state、getters、actions中定义的状态和方法可以直接被store实例访问,除了这些还有以下属性/方法

    • $id 定义状态时的id
    • $state 全部状态
    • $patch 修改状态
    • $reset 重置状态
    • $subscribe 订阅状态
    • $onAction 订阅Action

    $id

    $id为该store实例的ID,也就是defineStore的第一个参数

    1. const countStore = useCountStore()
    2. countStore.id // => 'count'
    3. 复制代码

    $state

    使用$state可以访问到全部状态,并且可以直接整个替换整个状态

    1. const countStore = useCountStore()
    2. countStore.$state = {count: countStore.count+1}
    3. 复制代码

    $patch

    $patch用来修改状态,可以直接传递个对象,也可以传递一个回调函数

    1. const countStore = useCountStore()
    2. // 传递对象
    3. countStore.$patch({
    4.  count: countStore.count+1
    5. })
    6. // 传递函数,函数第一个参数为state
    7. countStore.$patch(state=>{
    8.  state.count++
    9. })
    10. 复制代码

    $reset

    $reset用来重置状态,调用它所有的状态都会重置为初始值

    1. const countStore = useCountStore()
    2. countStore.$reset()
    3. 复制代码

    $subscribe

    $subscribe订阅状态

    第一个参数接受一个回调函数,当状态被修改时会调用回调函数

    第二个参数接受一个对象{ detached: true },detached默认false,设为true时当组件销毁时订阅不会取消

    1. const countStore = useCountStore()
    2. countStore.$subscribe((mutation, state) => {
    3.  console.log('mutation',mutation)
    4.  // 修改数据的方式
    5.  // 'direct': 通过countStore.count直接修改
    6.  // 'patch object' 使用countStore.$patch({})修改的数据
    7.  // 'patch function' 使用countStore.$patch((state)=>void)修改的数据
    8.  mutation.type
    9.  // 与 cartStore.$id 相同
    10.  mutation.storeId // 'cart'
    11.  // 仅适用于 mutation.type === 'patch object'
    12.  mutation.payload // 传递给$patch的对象
    13. },{ detached: true })
    14. 复制代码

    $onAction

    $onAction订阅Action,接受一个回调函数,当Action被调用时会调用回调函数

    1. const countStore = useCountStore()
    2. countStore.$onAction(
    3.   ({
    4.      name, // action 的名字
    5.      store, // store 实例
    6.      args, // 调用这个 action 的参数
    7.      after, // 在这个 action 执行完毕之后,执行这个函数
    8.      onError, // 在这个 action 抛出异常的时候,执行这个函数
    9.   })=>{
    10.      console.log(name,store,args,after,onError)
    11.      onError(()=>{
    12.        console.log('action 抛出异常')
    13.     })
    14. })
    15. 复制代码

    工具方法

    storeToRefs

    类似于toRefs,用于结构一个响应式对象,

    store 是一个用reactive 包裹的对象,这意味着不需要在getter 之后写.value,但是,就像setup 中的props 一样,我们不能对其进行解构

    1. const countStore = useCountStore()
    2. // 这不起作用,因为它会破坏响应式
    3. // 这和从 props 解构是一样的
    4. const { count, dbCount } = countStore
    5. 复制代码

    为了从 Store 中提取属性同时保持其响应式,您需要使用storeToRefs()。 它将为任何响应式属性创建 refs。 当您仅使用 store 中的状态但不调用任何操作时,这很有用:

    1. const countStore = useCountStore()
    2. const { count, dbCount } = storeToRefs(countStore)
    3. // (试了一下,用toRefs也能实现同样的效果)
    4. const { count, dbCount } = toRefs(countStore)


    链接:https://juejin.cn/post/7146009047311843342

  • 相关阅读:
    初次选购云服务器宽带如何选择?3M够吗?
    C++ 初识函数模板
    【C语言从入门到放弃 6】递归,强制类型转换,可变参数和错误处理详解
    几个常见的js手写题,你能写出来几道
    竞赛选题 深度学习+python+opencv实现动物识别 - 图像识别
    【git】本地仓库与远程仓库如何建立连接
    2022 年全球10大最佳自动化测试工具
    Python源码剖析3-列表对象PyListObject
    最优孤岛划分下含分布式电源配电网可靠性评估(Matlab代码实现)
    Docker的使用
  • 原文地址:https://blog.csdn.net/m0_71231013/article/details/127090725