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'], //设置需要缓存的对象
      },
    ],
  },
})
相关推荐
Devil枫26 分钟前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
尚梦1 小时前
uni-app 封装刘海状态栏(适用小程序, h5, 头条小程序)
前端·小程序·uni-app
GIS程序媛—椰子2 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js
前端青山2 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
毕业设计制作和分享2 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
dsywws2 小时前
Linux学习笔记之vim入门
linux·笔记·学习
从兄3 小时前
vue 使用docx-preview 预览替换文档内的特定变量
javascript·vue.js·ecmascript
晨曦_子画3 小时前
3种最难学习和最容易学习的 3 种编程语言
学习
城南vision3 小时前
Docker学习—Docker核心概念总结
java·学习·docker
ctrey_4 小时前
2024-11-1 学习人工智能的Day20 openCV(2)
人工智能·opencv·学习