vue3 pinia
学习记录来自 作者: 小满zs
学习地址
1. 简介pinia
Home | Pinia 中文文档 (web3doc.top)
pinia的特点:
- 完整的 ts 的支持;
- 足够轻量,压缩后的体积只有1kb左右;
- 去除 mutations,只有 state,getters,actions;
- actions 支持同步和异步;
- 代码扁平化没有模块嵌套,只有 store 的概念,store 之间可以自由使用,每一个store都是独立的
- 无需手动添加 store,store 一旦创建便会自动添加;
- 支持Vue3 和 Vue2
(1)安装
yarn add pinia -S
npm install pinia -S
(2)引入注册Vue3
main.ts
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')
vue2使用
import { createPinia, PiniaVuePlugin } from 'pinia'
Vue.use(PiniaVuePlugin)
const pinia = createPinia()
new Vue({
el: '#app',
// other options...
// ...
// note the same `pinia` instance can be used across multiple Vue apps on
// the same page
pinia,
})
2. 初始化Store
- 在src文件下创建文件夹(store)
- 在store文件夹下创建 [name].ts
- 创建一个store-namespace.ts存放唯一名称
export const enum Names {
Test = 'TEST'
}
- 引入store
import { defineStore } from 'pinia'
import { Names } from './store-namespace'
export const useTestStore = defineStore(Names.Test, {
})
- 定义相关值
import { defineStore } from 'pinia'
import { Names } from './store-namespace'
export const useTestStore = defineStore(Names.Test, {
state:()=>{
return {
current:1,
name:''
}
},
//类似于computed 可以帮我们去修饰我们的值
getters:{
},
//可以操作异步 和 同步提交state
actions:{
}
})
- 组件中使用
<template>current=>{{ current }}</template>
<script setup lang="ts">
import { useTestStore } from "./store/index";
const testStore = useTestStore();
const current = ref(testStore.current);
</script>
<style scoped></style>
3. 操作state
(1)直接修改
<template>
<button @click="change">change</button>
current=>{{ testStore.current }}
</template>
<script setup lang="ts">
import { useTestStore } from "./store/index";
const testStore = useTestStore();
const change = () => {
testStore.current++;
};
</script>
<style scoped></style>
(2)批量修改 patch
<template>
<button @click="change">change</button>
<div>current=>{{ testStore.current }} name=>{{ testStore.name }}</div>
</template>
<script setup lang="ts">
import { useTestStore } from "./store/index";
const testStore = useTestStore();
const change = () => {
testStore.$patch({
current: 10,
name: "change",
});
};
</script>
<style scoped></style>
函数带有state参数的形式,灵活性更高
<template>
<button @click="change">change</button>
<div>current=>{{ testStore.current }} name=>{{ testStore.name }}</div>
</template>
<script setup lang="ts">
import { useTestStore } from "./store/index";
const testStore = useTestStore();
const change = () => {
testStore.$patch((state) => {
state.current++;
state.name += "X";
});
};
</script>
<style scoped></style>
(3)通过原始对象修改整个实例
$state
您可以通过将store的属性设置为新对象来替换store的整个状态缺点就是必须修改整个对象的所有属性
<template>
<button @click="change">change</button>
<div>current=>{{ testStore.current }} name=>{{ testStore.name }}</div>
</template>
<script setup lang="ts">
import { useTestStore } from "./store/index";
const testStore = useTestStore();
const change = () => {
testStore.$state = {
current: 1,
name: "12",
};
};
</script>
<style scoped></style>
(4)通过actions修改
import { defineStore } from 'pinia'
import { Names } from './store-namespace'
export const useTestStore = defineStore(Names.Test, {
state: () => {
return {
current: 1,
name: ""
}
},
//类似于computed 可以帮我们去修饰我们的值
getters: {
},
//可以操作异步 和 同步提交state
actions: {
// 设置name
setName(name: string) {
this.name = name
}
}
})
<template>
<button @click="change">change</button>
<div>current=>{{ testStore.current }} name=>{{ testStore.name }}</div>
</template>
<script setup lang="ts">
import { useTestStore } from "./store/index";
const testStore = useTestStore();
// 使用
const change = () => {
testStore.setName("OKOK");
};
</script>
<style scoped></style>
4. 解构store
<template>
<div>origin value {{Test.current}}</div>
<div>
pinia:{{ current }}--{{ name }}
change :
<button @click="change">change</button>
</div>
</template>
<script setup lang='ts'>
import { useTestStore } from './store'
// 解决响应性丢失问题
import { storeToRefs } from 'pinia'
const Test = useTestStore()
const change = () => {
Test.current++
}
// const { current, name } = Test
// 解构state信息
const { current, name } = storeToRefs(Test)
console.log(current, name);
</script>
<style>
</style>
5. Actions
(1)同步调用
import { defineStore } from 'pinia'
import { Names } from './store-namespace'
export const useTestStore = defineStore(Names.TEST, {
state: () => ({
counter: 0,
}),
actions: {
increment() {
this.counter++
},
randomizeCounter() {
this.counter = Math.round(100 * Math.random())
},
},
})
<template>
<div>
<button @click="Add">+</button>
<div>
{{Test.counter}}
</div>
</div>
</template>
<script setup lang='ts'>
import {useTestStore} from './store'
const Test = useTestStore()
const Add = () => {
Test.randomizeCounter()
}
</script>
<style>
</style>
(2)异步调用
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: '小满',
isChu: true
})
}, 3000)
})
}
export const useTestStore = defineStore(Names.TEST, {
state: () => ({
user: <Result>{},
name: "123"
}),
actions: {
async getLoginInfo() {
const result = await Login()
this.user = result;
}
},
})
<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>
(3)相互调用
state: () => ({
user: <Result>{},
name: "default"
}),
actions: {
async getLoginInfo() {
const result = await Login()
this.user = result;
// 调用下面的setName
this.setName(result.name)
},
setName (name:string) {
this.name = name;
}
},
6. getters
使用箭头函数不能使用this this指向已经改变指向undefined 修改值请用state
主要作用类似于computed 数据修饰并且有缓存
- 普通函数形式
getters:{
newCurrent ():number {
return ++this.current
}
},
- getters 互相调用
getters:{
newCurrent ():number | string {
return ++this.current + this.newName
},
newName ():string {
return `$-${this.name}`
}
},
7. 常用API
(1)$reset
重置
store
到他的初始状态
state: () => ({
user: <Result>{},
name: "default",
current:1
}),
const reset = () => {
Test.$reset()
}
(2)$subscribe
类似于Vuex 的abscribe 只要有state 的变化就会走这个函数
Test.$subscribe((args,state)=>{
console.log(args,state);
})
如果你的组件卸载之后还想继续调用请设置第二个参数
Test.$subscribe((args,state)=>{
console.log(args,state);
},{
detached:true
})
(3)$onAction
只要有actions被调用就会走这个函数
Test.$onAction((args)=>{
console.log(args);
})