• 下一代Vuex(Pinia)不学你就out了


    为什么说不学Pinia你就out了。

    Pinia是下一代Vue状态管理库,在Vue-cli中已经替换了原来的Vuex,且同时支持Vue2.0和Vue3.0两个大版本。Pinia简化了状态管理,抛弃了Vuex中的mutation,只有 state, getteraction ,且完美支持TypeScript及Vue3.0的hooks,可以很好的进行代码分割。

    一、安装Pinia

    初始化项目: npm init vite@latest

    安装Pinia: npm i pinia

    import { createApp } from 'vue'
    import App from './App.vue'
    // 导入构造函数
    import { createPinia } from 'pinia'
    // 创建Vue应用实例app
    const app = createApp(App)
    // 应用以插件形式挂载Pinia实例
    app.use(createPinia())
    app.mount('#app')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    二、创建全局状态store

    // stores/counter.ts
    // 引入仓库定义函数
    import { defineStore } from 'pinia'
    // 传入2个参数,定义仓库并导出
    // 第一个参数唯一不可重复,字符串类型,作为仓库ID以区分仓库
    // 第二个参数,以对象形式配置仓库的state,getters,actions
    export const useCounterStore = defineStore('counter', {
      // 存储全局状态
      state: () => {
        return { name: 'hello pinia', count: 0 }
      },
      // 用来封装计算属性,有缓存功能,类似于computed
      getters: {
        getName(state) {
          return state.name + '...'
        }
      },
      // 处理业务逻辑,对state中的数据进行修改
      actions: {
        increment() {
          this.count++
        },
        subtract() {
          this.count--
        }
      }
    })
    
    • 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

    三、基本示例

    一旦仓库被实例化,就可以直接通过实例对象访问仓库上的stategettersactions中定义的任何属性。

    <template>
      <h1 style="color: blue">{{ store.getName }}</h1>
      <h2>数值变化:{{ store.count }}</h2>
      <button type="button" @click="store.increment">点击 + 1</button>
      <button type="button" @click="store.subtract">点击 - 1</button>
    </template>
    
    <script setup lang="ts">
    // 在需要使用状态的组件内需要先导入仓库:
    import { useCounterStore } from '../stores/counter'
    // 实例化仓库
    const store = useCounterStore()
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    四、数据解构

    Pinia中的store是一个用reactive包装的对象,不能直接通过ES6规范进行解构,因为这样做会使状态不具有响应性。

    在这里插入图片描述

    为了保持状态的响应行,应通过storeToRefsAPI 对仓库实例结构以便获取状态。

    <template>
      <h1 style="color: blue">name属性示例:{{ name }}</h1>
      <h1 style="color: green">getter属性示例:{{ store.getName }}</h1>
      <h1>数值变化:{{ count }}</h1>
      <button type="button" @click="store.increment">点击 + 1</button>
      <button type="button" @click="store.subtract">点击 - 1</button>
    </template>
    
    <script setup lang="ts">
    // 在需要使用状态的组件内需要先导入状态仓库:
    import { storeToRefs } from 'pinia'
    import { useCounterStore } from '../stores/counter'
    // 实例化仓库函数
    const store = useCounterStore()
    const { name, count } = storeToRefs(store)
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    五、数据修改

    Pinia中数据修改可以一次修改一个状态,也可以一次修改多个状态。

    修改单个状态比较简单,不像Vuex每次需要调用Vuex的api,Pinia中,修改单个状态,可直接通过仓库函数的实例直接调用。

    如以下示例中修改name值

    // stores/name.ts
    import { defineStore } from 'pinia'
    export const useCounterStore = defineStore('counter', {
      state: () => {
        return { name: 'hello pinia', count: 0 }
      },
      getters: {
        getName(state) {
          return state.name + '...'
        }
      },
      actions: {
        setName(val: string) {
          this.name = val
        },
        increment() {
          this.count++
        }
      }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    <template>
      <h1 style="color: blue">name属性示例:{{ store.name }}</h1>
      <h1 style="color: green">getter属性示例:{{ store.getName }}</h1>
      <button type="button" @click="store.setName('修改了name')">点击修改name</button>
    </template>
    <script setup lang="ts">
    import { useCounterStore } from '../stores/counter'
    const store = useCounterStore()
    </script>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    修改多条状态,Pinia中一次修改多条状态,需要通过官方提供的$patch$patch 方法可以接受的参数类型可以是一个函数也可以是一个对象对象。

    <template>
      <h1 style="color: blue">count:{{ store.count }}</h1>
      <h1 style="color: green">name:{{ store.name }}</h1>
      <button type="button" @click="changeState">点击修改store中的状态</button>
      <button type="button" @click="changeState2">点击修改store中的状态</button>
    </template>
    <script setup lang="ts">
    // 在需要使用状态的组件内需要先导入状态仓库:
    import { useCounterStore } from '../stores/counter'
    // 实例化仓库函数
    const store = useCounterStore()
    const changeState = () => {
      store.$patch({
        count: 2,
        name: '通过$patch的对象形式修改了名称'
      })
    }
    const changeState2 = () => {
      store.$patch(state => {
        state.count = 4
        state.name = '通过$patch的函数形式修改了名称'
      })
    }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    6、多仓库之间的调用

    在 Pinia 中,可以在一个 storeimport 另外一个 store ,然后通过调用引入 store 方法的形式,获取引入 store 的状态。
    在这里插入图片描述

    定义config

    // stores/config.ts
    import { defineStore } from 'pinia'
    export const useConfigStore = defineStore('config', {
      state: () => {
        return {
          primaryColor: '#5468ff'
        }
      },
      getters: {},
      actions: {}
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    定义name

    // stores/name.ts
    import { defineStore } from 'pinia'
    import { useConfigStore } from './config'
    export const useCounterStore = defineStore('counter', {
      state: () => {
        return { name: 'hello pinia', count: 0 }
      },
      getters: {
        getName(state) {
          return state.name + '...'
        }, 
        // 调用外部的store
        getConfig() {
          const config = useConfigStore()
          return config.primaryColor
        }
      },
      actions: {
        setName(val: string) {
          this.name = val
        },
        increment() {
          this.count++
        }
      }
    })
    
    • 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

    应用仓库数据

    <template>
      <h1 style="color: blue">count:{{ store.count }}</h1>
      <h1 style="color: green">name:{{ store.name }}</h1>
      <!-- 获取另外一个config中的配置 -->
      <h1 style="color: green">name:{{ store.getConfig }}</h1>
    </template>
    <script setup lang="ts">
    // 在需要使用状态的组件内需要先导入状态仓库:
    import { useCounterStore } from '../stores/name'
    // 实例化仓库函数
    const store = useCounterStore()
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    Pinia个人感触最深的是对于TypeScript的兼容,无论是在模板语法或者是逻辑处理中,都可以完美的提示仓库上的stategettersactions中定义的任何属性。

    7、往期内容已全部收录在专栏中:

    Flutter专栏_WEB前端李志杰的博客-CSDN博客

    Vue专栏_WEB前端李志杰的博客-CSDN博客

  • 相关阅读:
    JS中4种常见的内存泄漏
    芒果改进YOLOv5系列:首发结合最新NIPS2022华为诺亚的GhostNetV2 架构:长距离注意力机制增强廉价操作,打造高效轻量级检测器
    做期货的阶段(做期货的几个阶段)
    照明用哪种灯比较护眼?推荐专业的护眼照明灯
    Leetcode139. 单词拆分
    程序设计与实践 课程设计与实习报告
    深度解读传统品牌的NFT布局
    Spring事务简介说明
    WEB安全-SQL注入
    浏览器不能显示16位以上的数字
  • 原文地址:https://blog.csdn.net/qq_16221009/article/details/124784522