• vue3学习(十五)--- Pinia状态管理器


    Pinia官网地址点这里

    Pinia.js 有如下特点:

    1. 完整的 ts 的支持;
    2. 足够轻量,压缩后的体积只有1kb左右;
    3. 去除 mutations,只有 state,getters,actions
    4. actions 支持同步和异步;
    5. 代码扁平化没有模块嵌套,只有 store 的概念,store 之间可以自由使用,每一个store都是独立的
    6. 无需手动添加 storestore 一旦创建便会自动添加;
    7. 支持Vue3Vue2

    安装引入

    cnpm install pinia -S
    
    • 1
    import { createApp } from 'vue'
    import App from './App.vue'
    import {createPinia} from 'pinia'
     
    const store = createPinia()
    let app = createApp(App)
     
     
    app.use(store)
     
    app.mount('#app')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    这样就引入成功了,状态管理器使用要单独配置store/index.ts文件。然后在用到的页面中引入
    import {useTestStore} from './store',注意:引入和使用是分开的

    初始化仓库Store

    1. 创建文件store/index.ts
    2. 定义仓库Store
    import { defineStore } from 'pinia'
     
    export const useTestStore = defineStore('test', {
     	state:()=>{
     		return{
     			current:1
     		}
     	},
     	getters:{
     	},
     	actions:{
     	}
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 使用defineStore定义仓库,传唯一id。变量名称命名为use…是可组合项之间的约定,以使其使用习惯。
      • 唯一的id。类似于vue2module模块的功能,这样更加的方便。
    • State 箭头函数 返回一个对象 在对象里面定义值
    • getters类似计算属性
    • actions里面可以定义同步和异步

    页面使用

    引入对应的store名称useTestStore,然后执行useTestStore()

    <template>
         <div>
             <button @click="Add">+</button>
              <div>
                 {{Test.current}}
              </div>
         </div>
    </template>
     
    <script setup lang='ts'>
    import {useTestStore} from './store'
    const Test = useTestStore()
    const Add = () => {
        Test.current++
    }
     
    </script>
     
    <style>
     
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    state

    1. 直接修改state

    // 直接修改state
    const editState = ()=>{
      TestStore.current++
    }
    
    • 1
    • 2
    • 3
    • 4

    2. 批量修改State的值 $patch对象形式

    const editState2 = ()=>{
      TestStore.$patch({
        current:200,
           name:300
      })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3. 批量修改State的值 $patch函数形式

    函数默认state参数,传递给 $patch() 的函数必须是同步的。

    推荐使用函数形式 可以自定义修改逻辑比如if判断

    const editState3 = ()=>{
      TestStore.$patch((state)=>{
        state.current = 300
        state.name = 300
      })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4. 通过actions修改 使用方法直接在实例调用

    const editState4 = ()=>{
      TestStore.setCurrent()
    }
    
    • 1
    • 2
    • 3
    // pinia没有mutation 只有actions 同步异步都在这里处理
      actions: {
        // 同步
        setCurrent() {
          console.log('this', this)
          this.current++
        }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    解构store

    Pinia不允许直接解构是会失去响应性的

    const Test = useTestStore()
     
     
    const { current, name } = Test
     
    console.log(current, name);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这种是不具有响应式的

    要想得到响应式效果需要使用pinia自带的storeToRefs

    import { storeToRefs } from 'pinia'
     
    const Test = useTestStore()
     
    const { current, name } = storeToRefs(Test)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    其原理跟toRefs 一样的给里面的数据包裹一层toref。

    源码通过toRaw使store变回原始数据防止重复代理。循环store 通过 isRef isReactive 判断 如果是响应式对象直接拷贝一份给refs 对象 将其原始对象包裹toRef 使其变为响应式对象


    getters

    主要作用类似于computed 数据修饰并且有缓存

    getters: {
        terCurrent(): string {
          return `getters:普通调用可以使用this访问属性--------${this.current}`
        },
        terCurrent2: (state) => {
          return `getters:箭头函数无法使用this 需要使用getters默认第一个参数state访问---- ${state.current}`
        },
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    普通函数形式可以使用this,箭头函数不能使用this,可以使用state参数


    actions 同步和异步

    同步

    同步直接调用即可

    const editState4 = ()=>{
      TestStore.setCurrent()
    }
    
    • 1
    • 2
    • 3
    // pinia没有mutation 只有actions 同步异步都在这里处理
      actions: {
        // 同步
        setCurrent() {
          console.log('this', this)
          this.current++
        }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    异步

    异步 可以结合async await 修饰

    import { defineStore } from 'pinia'
    import { Names } from './store-naspace'
     
    type Result = {
        name: string
        isChu: boolean
    }
     
    const Login = (): Promise<Result> => {
        return new Promise((resolve) => {
            setTimeout(() => {
                resolve({
                    name: '4444',
                    isChu: true
                })
            }, 3000)
        })
    }
     
    export const useTestStore = defineStore('test' {
        state: () => ({
            user: <Result>{},
            name: "123"
        }),
        actions: {
            async getLoginInfo() {
                const result = await Login()
                this.user = result;
            }
        },
    })
    
    • 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
    <template>
         <div>
             <button @click="Add">test</button>
              <div>
                 {{Test.user}}
              </div>    
         </div>
    </template>
     
    <script setup lang='ts'>
    import {useTestStore} from './store'
    const Test = useTestStore()
    const Add = () => {
         Test.getLoginInfo()
    }
     
    </script>
     
    <style>
     
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    常见API

    $reset()

    重置store到它的初始状态

    const resetFn=()=>{
      TestStore.$reset()
    }
    
    • 1
    • 2
    • 3

    $subscribe

    订阅state的改变,只要有state 的变化就会走这个函数

    Test.$subscribe((args,state)=>{
       console.log(args,state);
    })
    
    • 1
    • 2
    • 3

    $onAction

    订阅Actions的改变,只要有actions被调用就会走这个函数

    Test.$onAction((args)=>{
       console.log(args);
    })
    
    • 1
    • 2
    • 3

    pinia插件

    pinia和vuex一样,一旦刷新页面就会数据丢失。

    一般会设计一个插件,将state缓存起来。

    const __piniaKey = '__PINIAKEY__'
    //定义兜底变量
     
     
    type Options = {
       key?:string
    }
    //定义入参类型
     
     
     
    //将数据存在本地
    const setStorage = (key: string, value: any): void => {
     
    localStorage.setItem(key, JSON.stringify(value))
     
    }
     
     
    //存缓存中读取
    const getStorage = (key: string) => {
     
    return (localStorage.getItem(key) ? JSON.parse(localStorage.getItem(key) as string) : {})
     
    }
     
     
    //利用函数柯丽华接受用户入参
    const piniaPlugin = (options: Options) => {
     
    //将函数返回给pinia  让pinia  调用 注入 context
    return (context: PiniaPluginContext) => {
     
    const { store } = context;
     
    const data = getStorage(`${options?.key ?? __piniaKey}-${store.$id}`)
     
    store.$subscribe(() => {
     
    setStorage(`${options?.key ?? __piniaKey}-${store.$id}`, toRaw(store.$state));
     
    })
     
    //返回值覆盖pinia 原始值
    return {
     
    ...data
     
    }
     
    }
     
    }
     
     
    //初始化pinia
    const pinia = createPinia()
     
     
    //注册pinia 插件
    pinia.use(piniaPlugin({
     
    key: "pinia"
     
    }))
    
    • 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
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    pinia持久化工具pinia-plugin-persist

    安装

    npm i pinia-plugin-persist --save
    
    • 1

    引入

    main.ts
    
    // 引入状态管理器
    import { createPinia } from 'pinia'
    import piniaPluginPersist from 'pinia-plugin-persist'
    
    // pinia添加数据持久化插件
    const pinia = createPinia()
    pinia.use(piniaPluginPersist)
    
    app.use(pinia)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    ts声明文件

    在根目录创建types文件夹存放类似这种没有声明文件的情况。创建pinia-plugin-persist.d.ts文件(ts会全局检查.d.ts文件)

    declare module 'pinia-plugin-persist'
    
    • 1
    import { defineStore } from 'pinia'
    
    export const Store = defineStore('comStore', {
      // 类似于Vue2组件中的data,用于存储全局状态数据,但有两个要求
      // 1. 必须是函数,目的是为了在服务端渲染的时候避免交叉请求导致的数据状态污染
      // 2. 必须是箭头函数,这样是为了更好的 TS 类型推导
      state: () => {
        return {
        }
      },
      getters: {
      },
      actions: {
      },
      persist: {
        enabled: true, // true 表示开启持久化保存
        strategies: [
          {
            key: 'user', //设置缓存名称
            storage: sessionStorage, //设置缓存方式
            paths: ['userInfo'], //设置需要缓存的对象
          },
        ],
      },
    })
    
    • 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
  • 相关阅读:
    AMS 和 WMS的关系是什么,他们是同一个进程吗?
    GEE|时间序列分析(五)
    Tensorflow笔记(二)
    电动平衡车UL2272测试哪些项目
    如何实现人机界面与多台plc之间无线通讯?
    C#:基本语法
    A37 STM32_HAL库函数 之PCD通用驱动 -- C-- 所有函数的介绍及使用
    C++ 多线程
    CH9101芯片应用—硬件设计指南
    [深入研究4G/5G/6G专题-48]: 5G Link Adaption链路自适应-4-下行链路自适应DLLA-PDCCH信道
  • 原文地址:https://blog.csdn.net/weixin_43932245/article/details/134123710