当前位置:网站首页>学习pinia 介绍-State-Getters-Actions-Plugins
学习pinia 介绍-State-Getters-Actions-Plugins
2022-07-26 12:53:00 【AIpoem】
可爱小菠萝,安排一下!
内容基本参考官网:
https://pinia.vuejs.org
(官网的字体是Dank mono 不知道有没有跟我一样很喜欢的朋友 已经美美换上
介绍
pinia:最新一代的轻量级状态管理插件
如果你之前使用过 vuex 进行状态管理的话,那么 pinia 就是一个类似的插件
优点:
- 完整的ts支持
- 轻量
- 去除了mutations,只有state、getters、actions
…
安装
npm i pinia
引入注册
// main.ts
import {
createApp } from 'vue'
import App from './App.vue'
import {
createPinia} from 'pinia'
const app = createApp(App);
const store = createPinia();
app.use(store);
初始化仓库Store
1.根目录下新建store文件夹,再建一个index.ts
2.main.tsstore是用defineStore()定义的
第一个参数传一个唯一的名称
第二个参数还可以传一些别的比如getters、actions之类的,后面再说
import {
defineStore } from "pinia";
export const useUserStore = defineStore('user', {
state: () => ({
// 初始化的值
name: 'AIpoem',
age: 20
}),
actions: {
changeInfo() {
this.name = 'change poem'
},
},
})
3.在组件中使用
实例化store之后,可以直接在store上访问任何定义在state、getters、actions的属性store是经过reactive包装的对象,这意味着我们不需要写.value,但是就类似于props,我们是不能解构store的
<script setup lang="ts"> import {
useUserStore } from "./store"; const userStore = useUserStore(); // 这样会丢失响应性 const {
name, age } = userStore; </script>
<template>
{
{ userStore.name }},{
{ userStore.age }}
</template>
如果需要从store中提出属性,同时保持其响应性,我们要用storeToRefs()
它会为每一个属性都包上一层ref(会跳过action和任何不具有响应性的属性
并且,action我们可以直接解构,它也是绑定在store身上的
<script setup lang="ts"> import {
useUserStore } from "../store"; import {
storeToRefs } from "pinia"; const userStore = useUserStore(); const {
name, age } = storeToRefs(userStore); const {
changeInfo } = userStore; </script>
State
访问State
可以通过store实例直接对state进行读和写
const userStore = useUserStore();
userStore.name = 'change poem';
重置State
可以调用store实例上的$reset()方法将state重置为初始值
const userStore = useUserStore();
console.log(userStore.name); // AIpoem
userStore.name = "change poem";
userStore.$reset();
console.log(userStore.name); // AIpoem
改变State
除了用store实例直接改变State(userStore.name = "change poem"),也可以调用$patch()方法
使用$patch()方法可以批量修改state
1.$patch()传一个对象
允许你对state进行部分更改
const userStore = useUserStore();
userStore.$patch({
name: "change poem",
})
2.$patch()传一个函数
但是当state中有数组的时候,上面那种传对象的方法就不太好用了,比如数组要新增、要删除一个元素,我们都要创建一个新数组来更新
那这种时候传函数就更方便
// 我上面的例子state中没有数组,这里就加一个数组演示一下
// state: () => ({
// // 初始化的值
// name: "AIpoem",
// age: 20,
// hobby: ["吃", "喝", "玩", "乐"],
// }),
const userStore = useUserStore();
// 这个state就是store实例上的state
userStore.$patch(state => {
state.hobby.push("睡")
})
// 传对象写法
// userStore.$patch({
// hobby: ["吃", "喝", "玩", "乐", "睡"]
// })
替换State
你可以给store实例的$state属性赋值一个新对象,这样能替换掉整个state
const userStore = useUserStore();
userStore.$state = {
name: "change poem",
age: 120,
hobby: ["吃", "喝", "玩", "乐", "睡"],
};
订阅状态
你可以通过store实例的$subscribe()方法来监视state的变化$subscribe()有两个参数:
第一个参数是一个回调函数:
const userStore = useUserStore();
userStore.$subscribe((mutation, state) => {
// 可能值:‘direct’ 'patch object' 'patch function'
console.log(mutation.type) // 修改的方式
console.log(mutation.storeId) // defineStore()时传的名字
})
第二个参数是固定值: { detached: true }
当组件卸载的时候,state的订阅也会自动卸载,如果我们希望订阅在组件卸载后还能保留,那就传第二个参数
const userStore = useUserStore();
userStore.$subscribe((mutation, state) => {
...
}, {
detached: true })
Getters
相当于store实例的computed,用来修饰值,并且是有缓存的
如果只需要用到state,直接用就行
export const useUserStore = defineStore('user', {
state: () => ({
name: 'AIpoem',
}),
getters: {
sayName: state => `我的名字是${
state.name}`
}
})
使用this
如果需要用到其他getter,我们可以通过this来访问store实例
使用了this的注意点:
1.用了this就不能用箭头函数,否则this不指向store实例
2.在ts中有必要定义返回值的类型
export const useUserStore = defineStore('user', {
state: () => ({
// 初始化的值
name: 'AIpoem',
}),
getters: {
sayName: state => `我的名字是${
state.name}`,
sayHi():string {
return `你好, ${
this.sayName}`
}
}
})
模板中使用,就跟用computed一样
<script setup lang="ts"> import {
useUserStore } from "../store"; const userStore = useUserStore(); </script>
<template>
{
{ userStore.sayName }} <br />
{
{ userStore.sayHi }}
</template>

传参
getters的传参方法也跟computed一样,就是return一个function,用这个function来接收参数
export const useUserStore = defineStore('user', {
state: () => ({
name: 'AIpoem',
}),
getters: {
isMyName: state => {
return function(userName: string):boolean {
return state.name === userName
}
}
// 简写
// isMyName: state => (userName: string) => state.name === userName
}
})
模板中直接传参就行:
<script setup lang="ts"> import {
useUserStore } from "../store"; const userStore = useUserStore(); </script>
<template>
{
{ userStore.isMyName("AIpoem") }} <br />
{
{ userStore.isMyName("111") }}
</template>

️:如果getters返回了一个函数,它将不再缓存
Actions
相当于store实例的methods
支持同步也支持异步
同步
import {
defineStore } from "pinia";
interface User {
name: string,
age: number
}
export const useUserStore = defineStore('user', {
state: () => ({
userInfo: <User>{
},
}),
actions: {
setUserInfo() {
this.userInfo = {
name: 'AIpoem',
age: 20
}
}
}
})
异步
一般结合async await一起使用
import {
defineStore } from "pinia";
interface User {
name: string,
age: number
}
const getInfo = (): Promise<User> => {
return new Promise(resolve => {
setTimeout(() => {
resolve({
name: 'AIpoem',
age: 20,
})
}, 3000)
})
}
export const useUserStore = defineStore('user', {
state: () => ({
userInfo: <User>{
},
}),
actions: {
async setUserInfo() {
this.userInfo = await getInfo()
}
}
})
订阅actions
可以使用store实例的$onAction()方法来监视actions的调用$onAction()有两个参数:
第一个参数是一个回调函数:
userStore.$onAction(args => {
// 调用的那个action的名字
console.log(args.name);
// store实例
console.log(args.store);
// action成功调用并运行完触发
args.after(() => {
console.log("after");
});
// action抛错或返回一个失败的promise时触发
args.onError(() => {
console.log("出错了");
});
});
第二个参数是固定值: true
当组件卸载的时候,action的订阅也会自动卸载,如果我们希望订阅在组件卸载后还能保留,那就传第二个参数
userStore.$onAction(args => {
// 调用的那个action的名字
console.log(args.name);
// store实例
console.log(args.store);
// action成功调用并运行完触发
args.after(() => {
console.log("after");
});
// action抛错或返回一个失败的promise时触发
args.onError(() => {
console.log("出错了");
});
}, true);
Plugins
我们可以通过写插件对pinia的store进行一些扩展
和vue一样,通过pinia.use()注册插件
pinia的插件是一个函数
pinia内部会帮我们调用这个插件函数,并且传回来一个可选的参数context
( 这部分演示的是js的写法,如果是ts还需要加一些东西,放在更后面了
// main.js
import {
createApp, markRaw } from 'vue'
import {
router } from './router'
import {
createPinia } from 'pinia'
const myPiniaPlugin = (context) => {
// defineStore()时传进去的第二个参数
console.log(context.options);
// store实例
console.log(context.store);
// 可以给store实例添加一个全局属性
context.store.globalProperty = '我是一个全局属性'
// 可以给store实例添加一个新的state
context.store.$state.newProperty = context.store.globalProperty;
// $state可读可写
console.log(context.store.$state); // Proxy {newProperty: '我是一个全局属性'}
// 添加第三方库的实例,需要用markRow()包裹,标记为不可响应式
context.store.router = markRow(router)
// 这两个订阅也可以调,在里面处理一些需要的逻辑
context.store.$subscribe(() => {
})
context.store.$onAction(() => {
})
}
const app = createApp(App)
const store = createPinia()
store.use(myPiniaPlugin)
app.use(store)
在defineStore()时可以传第三个参数,他会出现在的context.options中,这样我们可以利用自定义的第三个参数来做一些事情
使用ts编写插件:context的类型是PiniaPluginContext,这个要导进来写上
1.如果为store实例添加了新的属性
需要扩展PiniaCustomProperties接口
// main.ts
import 'pinia'
import {
createPinia, PiniaPluginContext} from 'pinia'
declare module 'pinia' {
export interface PiniaCustomProperties {
globalProperty: string
}
}
const myPiniaPlugin = (context: PiniaPluginContext) => {
// 给store实例添加一个全局属性
context.store.globalProperty = '我是一个全局属性'
}
2.如果给store实例添加了新的state
需要扩展PiniaCustomStateProperties接口
...
declare module 'pinia' {
export interface PiniaCustomStateProperties {
newProperty: string
}
}
const myPiniaPlugin = (context: PiniaPluginContext) => {
// 给store实例添加一个全局属性
context.store.$state.newProperty = context.store.globalProperty;
}
...
3.如果添加了新的创建选项,也就是给defineStore()传了第三个参数
需要扩展DefineStoreOptionsBase接口
// 这我也不知道举什么例子了
declare module 'pinia' {
export interface DefineStoreOptionsBase {
...
}
}
(最后部分整的有点潦草我清楚我明白,原因是我还没有参透ts)
(等我学成归来xx等我需要用到的时候再研究一下)
(详情请咨询https://pinia.vuejs.org)
边栏推荐
- Food safety | these common foods are poisonous! Check your dining table quickly
- 虚拟偶像代言产品出问题谁负责?且听律师分析
- RMII, smii, gmii, rgmii interfaces of Ethernet Driver
- Flutter integrated Aurora push
- VS code 设置Ctrl+S保存,自动格式化的方法
- jvm:类加载子系统干什么的?由什么组成?需要记住哪些八股文?
- Use grid to realize left, middle and right layout, and the middle content is adaptive
- 代码报错解决问题经验之二:YOLOv5中的test报错
- [typescript] typescript common types (Part 1)
- Router. Push(), router. Reply(), router. Go()
猜你喜欢

Food safety | is self-made food purchased online healthy food? Don't fall into these misunderstandings

今日睡眠质量记录75分

Qualcomm once again "bet" on Zhongke Chuangda to challenge the full stack solution of intelligent driving software and hardware

二叉树的初阶笔记

历史上的今天:IBM 获得了第一项专利;Verizon 收购雅虎;亚马逊发布 Fire Phone...

Kubernetes ---- life cycle introduction of PV and PVC

【TypeScript】TypeScript常用类型(下篇)

VS code 设置Ctrl+S保存,自动格式化的方法

一款超好用的神器Apifox,甩 Swagger 几条街...(荣耀典藏版)

【5GC】什么是5G切片?5G切片如何工作?
随机推荐
Kubernetes---- installing and deploying NFS servers
[typescript] typescript common types (Part 1)
LCD笔记(4)分析内核自带的LCD驱动程序
Analysis of Wireshark data package of network security B module of national vocational college skills competition Wireshark 0051.pcap
Examples of ThreadLocal usage scenarios under multithreading
SLAM 02.整体框架
Kubernetes----Kubernetes常用插件简介
Azure Synapse Analytics 性能优化指南(2)——使用具体化视图优化性能(上)
Kuzaobao: summary of Web3 encryption industry news on July 25
数据库组成存储过程和函数
父组件访问子组件的方法或参数 (子组件暴漏出方法defineExpose)
1-6月中国ADAS供应商占比9% 又一家零部件巨头全面布局智驾新赛道
In the digital era, what "golden treasure" is driving the development of pharmaceutical enterprises for a century?
Detailed explanation of redis's single login
Remote IP debugger (Practical dry goods)
Transformer dominates the world? Depth wise conv has something to say
可移动表空间
Panorama of volcanic engine cloud growth plan: 30 + plans come out together, and military development advantage areas
Emerging security providers to learn about in 2022
维度灾难 维数灾难 暂记