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

文章目录

Pinia官网地址点这里

Pinia.js 有如下特点:

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

安装引入

javascript 复制代码
cnpm install pinia -S
javascript 复制代码
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')

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

初始化仓库Store

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

页面使用

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

javascript 复制代码
<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>

state

1. 直接修改state

javascript 复制代码
// 直接修改state
const editState = ()=>{
  TestStore.current++
}

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

javascript 复制代码
const editState2 = ()=>{
  TestStore.$patch({
    current:200,
       name:300
  })
}

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

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

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

javascript 复制代码
const editState3 = ()=>{
  TestStore.$patch((state)=>{
    state.current = 300
    state.name = 300
  })
}

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

javascript 复制代码
const editState4 = ()=>{
  TestStore.setCurrent()
}
javascript 复制代码
// pinia没有mutation 只有actions 同步异步都在这里处理
  actions: {
    // 同步
    setCurrent() {
      console.log('this', this)
      this.current++
    }
 }

解构store

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

javascript 复制代码
const Test = useTestStore()
 
 
const { current, name } = Test
 
console.log(current, name);

这种是不具有响应式的

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

javascript 复制代码
import { storeToRefs } from 'pinia'
 
const Test = useTestStore()
 
const { current, name } = storeToRefs(Test)

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

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


getters

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

javascript 复制代码
getters: {
    terCurrent(): string {
      return `getters:普通调用可以使用this访问属性--------${this.current}`
    },
    terCurrent2: (state) => {
      return `getters:箭头函数无法使用this 需要使用getters默认第一个参数state访问---- ${state.current}`
    },
  },

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


actions 同步和异步

同步

同步直接调用即可

javascript 复制代码
const editState4 = ()=>{
  TestStore.setCurrent()
}
javascript 复制代码
// pinia没有mutation 只有actions 同步异步都在这里处理
  actions: {
    // 同步
    setCurrent() {
      console.log('this', this)
      this.current++
    }
 }

异步

异步 可以结合async await 修饰

javascript 复制代码
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;
        }
    },
})
javascript 复制代码
<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>

常见API

$reset()

重置store到它的初始状态

javascript 复制代码
const resetFn=()=>{
  TestStore.$reset()
}

$subscribe

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

javascript 复制代码
Test.$subscribe((args,state)=>{
   console.log(args,state);
})

$onAction

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

javascript 复制代码
Test.$onAction((args)=>{
   console.log(args);
})

pinia插件

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

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

javascript 复制代码
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"
 
}))

pinia持久化工具pinia-plugin-persist

安装

javascript 复制代码
npm i pinia-plugin-persist --save

引入

javascript 复制代码
main.ts

// 引入状态管理器
import { createPinia } from 'pinia'
import piniaPluginPersist from 'pinia-plugin-persist'

// pinia添加数据持久化插件
const pinia = createPinia()
pinia.use(piniaPluginPersist)

app.use(pinia)

ts声明文件

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

javascript 复制代码
declare module 'pinia-plugin-persist'
javascript 复制代码
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'], //设置需要缓存的对象
      },
    ],
  },
})
相关推荐
南宫生2 分钟前
力扣每日一题【算法学习day.132】
java·学习·算法·leetcode
技术小齐22 分钟前
网络运维学习笔记 016网工初级(HCIA-Datacom与CCNA-EI)PPP点对点协议和PPPoE以太网上的点对点协议(此处只讲华为)
运维·网络·学习
竹言笙熙30 分钟前
代码审计初探
学习·web安全
日记成书32 分钟前
物联网智能项目
物联网·学习
dorabighead1 小时前
JavaScript 高级程序设计 读书笔记(第三章)
开发语言·javascript·ecmascript
虾球xz1 小时前
游戏引擎学习第118天
学习·游戏引擎
css趣多多1 小时前
案例自定义tabBar
前端
gz927cool1 小时前
大模型做导师之开源项目学习(lightRAG)
学习·开源·mfc
姑苏洛言2 小时前
DeepSeek写微信转盘小程序需求文档,这不比产品经理强?
前端
林的快手3 小时前
CSS列表属性
前端·javascript·css·ajax·firefox·html5·safari