当前位置:网站首页>学习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)
边栏推荐
- MySQL可以自定义变参存储函数吗?
- LCD notes (5) LCD driver framework_ Use device tree
- After being fined "paid leave" for one month, Google fired him who "loves" AI
- Remote IP debugger (Practical dry goods)
- The programmed navigation route jumps to the current route (the parameters remain unchanged), and if it is executed multiple times, it will throw a navigationduplicated warning error?
- What is the Internet of things? The most comprehensive explanation of common IOT protocols
- 0基础编程资源大全(先收藏~慢慢看~)
- Ue5 official case Lyra full feature explanation 7. resource management
- 关于图片地址链接复制问题
- 今日睡眠质量记录75分
猜你喜欢

LCD notes (7) LCD driver framework_ Configure clock

V00 - do whatever you want when you are old

今日睡眠质量记录75分

0基础编程资源大全(先收藏~慢慢看~)

食品安全 | 这些常见食物小心有毒!速查自家餐桌

Huawei recruited "talented teenagers" twice this year; 5.4 million twitter account information was leaked, with a selling price of $30000; Google fired engineers who believed in AI consciousness | gee

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

Kubernetes----PV和PVC的生命周期简介

Food safety | can you eat any fruit?

Today in history: IBM obtained the first patent; Verizon acquires Yahoo; Amazon releases fire phone
随机推荐
华为超融合FusionCube解决方案笔记
父组件访问子组件的方法或参数 (子组件暴漏出方法defineExpose)
若有声明”int x=5,y=1;”,则表达式x<y?x++:y++的结果是:
The database consists of stored procedures and functions
Bitwise and how to write SQL
What is the Internet of things? The most comprehensive explanation of common IOT protocols
Display inline+calc realizes left, middle and right layout, and the middle is adaptive
Kubernetes---- installing and deploying NFS servers
Huawei ultra fusion fusioncube solution notes
Does anyone know where the retract of flinksql can be specified? Only api code settings can be seen in online materials
历史上的今天:IBM 获得了第一项专利;Verizon 收购雅虎;亚马逊发布 Fire Phone...
Reflection, an implementation of automatic repeated call interface
Streamnational team culture: a "transparent" company
Huawei recruited "talented teenagers" twice this year; 5.4 million twitter account information was leaked, with a selling price of $30000; Google fired engineers who believed in AI consciousness | gee
Does Flink CDC only support SQL client to submit SQL scripts
Can MySQL customize variable parameter storage functions?
Kubernetes----高级存储之PV和PVC简介
二叉树的初阶笔记
Shell变量和引用
Removable tablespace