• vue3新一代状态管理器 — pinia的学习与使用


    一、vuex与pinia

    在这里插入图片描述

    Pinia 最初是为了探索 Vuex 的下一次迭代会是什么样子,结合了 Vuex 5 核心团队讨论中的许多想法。最终,我们意识到 Pinia 已经实现了我们在 Vuex 5 中想要的大部分内容,并决定实现它 取而代之的是新的建议。

    可以理解为pinia就是下一代的vuex5,但是vuex团队为了尊重pinia作者对于vuex的开发贡献,就直接使用pinia命名了。
    pinia中文文档

    特性

    1. 完全支持typescript
    2. 足够轻量,压缩后体积只有1.6kb
    3. 模块化的设计,在打包时引入的每一个store都可以自动拆分
    4. 没有模块嵌套,只有store概念,store之间可以自由使用,实现更好的代码分隔
    5. actions支持同步和异步,去除了mutation
    6. 支持VueDevtools

    二、使用pinia

    2.1 安装pinia

    用你最喜欢的包管理器安装 pinia:

    yarn add pinia
    # 或者使用 npm
    npm install pinia
    
    • 1
    • 2
    • 3

    2.2 项目引入

    使用createPinia将pinia引入项目中。

    main.ts:

    import { createPinia } from 'pinia'
    import { createApp } from 'vue'
    import App from './App.vue'
    
    createApp(App).use(createPinia()).mount('#app')
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.3 创建store

    src目录下创建store文件夹,用于存放store对应的js/ts文件,未来方便管理,我们可以在一个js/ts文件中只定义一个store,例如我们定义一个user.ts文件,用于存储用户相关的信息和操作:
    在这里插入图片描述
    pinia使用defineStore创建store,包含了id、state、getters和actions:

    // @ts-check
    import { defineStore } from 'pinia'
    
    /**
     * Simulate a login
     */
    function apiLogin(a: string, p: string) {
      if (a === 'ed' && p === 'ed') return Promise.resolve({ isAdmin: true })
      if (p === 'ed') return Promise.resolve({ isAdmin: false })
      return Promise.reject(new Error('invalid credentials'))
    }
    
    export const useUserStore = defineStore({
      id: 'user',
      state: () => ({
        name: 'Eduardo',
        isAdmin: true,
      }),
      
      getters:{
    	userName: (state) => `Get userName from getter ${state.name}`
      },
      
      actions: {
      /**
      * 退出logout
      */
        logout() {
          this.$patch({
            name: '',
            isAdmin: false,
          })
      /**
       * 登录 login
       */
        async login(user: string, password: string) {
          const userData = await apiLogin(user, password)
          this.$patch({
            name: user,
            ...userData,
          })
        },
      },
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    相比较于vuex,pinia去除了mutation,同步和异步操作都通过actions,并且没有了module的概念,defineStore会创建一个新的store。

    2.4 使用store

    在组件中引入定义好的store并调用:

    <script setup lang="ts">
    import { useUserStore } from "./store/user"
    
    const userStore = useUserStore()
    
    //访问state
    console.log(userStore.name)
    //访问getter
    console.log(userStore.userName)
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    然后就可以通过user来访问store中的state,并且还可以调用getter和action。

    getter

    Getter 完全等同于 Store 状态的计算值。 它们可以用 defineStore() 中的 getters 属性定义。 他们接收“状态”作为第一个参数以鼓励箭头函数的使用,可以直接在 store 实例上访问 getter。
    我们也可以在定义常规函数时通过 this 访问到整个 store 的实例。

    action

    Actions 相当于组件中的 methods。 它们可以使用 defineStore() 中的 actions 属性定义,并且它们非常适合定义业务逻辑,也可以直接在store实例上调用action。
    在actions中也可以在定义常规函数时通过 this 访问到整个 store 的实例。

    export const useStore = defineStore('main', {
      state: () => ({
        counter: 0,
      }),
      actions: {
        increment() {
          this.counter++
        },
        randomizeCounter() {
          this.counter = Math.round(100 * Math.random())
        },
      },
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2.5 修改state

    1、直接修改

    虽然可以通过pinia实例直接修改,但是出于代码结构来说,全局的状态管理还是不要直接在各个组件处随意修改状态,应放于 action 中统一方法修改(piain没有mutation)并不推荐!

    store.count ++;
    
    • 1

    2、使用$patch

    使用$patch改变数据 $patch 可以同时修改多个值。

    store.$patch((state) => {
            state.name= 'newName'
            state.age ++
          })
    
    • 1
    • 2
    • 3
    • 4

    3、使用actions

    推荐。

    actions:{
        async login(user: string, password: string) {
          //模拟异步登录
          const userData = await apiLogin(user, password)
          //更新state中数据
          this.$patch({
            name: user,
            ...userData,
          })
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2.6 storeToRefs

    为了直接获取store中的属性,我们可能会利用解构来直接获取:

    import { useUserStore } from "./store/user"
    
    const { name }= useUserStore()
    
    • 1
    • 2
    • 3

    但是,值得注意的是,如果直接解构store实例来获取state中的值,那么获取的值就失去了响应式,正确的做法是使用storeToRefs:

    import { storeToRefs } from 'pinia'
    import { useUserStore } from "./store/user"
    
    const { name }= storeToRefs(useUserStore())
    
    • 1
    • 2
    • 3
    • 4
  • 相关阅读:
    华为云云耀云服务器L实例评测|企业项目最佳实践之华为云耀云服务器L实例介绍(三)
    大咖说|翼辉丁晓华:我们已经真正意义上感受到了原始创新带来的巨大价值
    Can‘t locate Bio/SeqIO.pm in @INC
    Node-工具模块
    MongoDB 分片集群
    库调多了,都忘了最基础的概念 -HashMap 篇
    我的创作纪念日--码农阿豪
    哪个塑胶ERP系统比较好?常用塑胶ERP软件有哪些
    css 居中
    webpack定制化 基础配置[基础、配置、初运行]
  • 原文地址:https://blog.csdn.net/ZHANGYANG_1109/article/details/128036448