介绍
什么是Pinia
Pinia是vue.js轻量级的状态管理库,类似Vuex,同时支持vue2与vue3。
Pinia的特性
- 极轻, 仅有 1 KB
- 清晰、显式的代码拆分
- 不支持嵌套的模块,通过组合
store
来代替 - 去掉
mutations
,只有state
、getters
和actions
- 支持
composition-api
和options-api
- 更完善的
typescript
支持
使用
安装
yarn add pinia;
引入
import { createApp } from 'vue';
import App from './App.vue';
import { createPinia } from 'pinia';
const app = createApp(App);
const pinia = createPinia();
app.use(pinia);
app.mount('#app');
创建一个store
import { defineStore } from 'pinia';
export const usePerson = defineStore('person', {
state: () => {
return {
name: '李四',
age: 18,
merried: false
}
},
getters: {
info() {
return `我叫${this.name},今年${this.age}岁,${this.merried ? '已婚' : '未婚'}。`;
}
}
})
在组件中使用
<script setup>
import {usePerson} from "../../store/person";
const person = usePerson();
</script>
<p>姓名:{{person.name}}</p>
<p>年龄:{{person.age}}</p>
<p>已婚:{{person.merried}}</p>
<p>自我介绍:{{person.info}}</p>
如果我们想解构 person
, 需要使用 storeToRefs
来转成响应式数据。
import { storeToRefs } from "pinia";
const { name, age, merried, info } = storeToRefs(person);
这样就能直接使用 person
里的字段了
<p>姓名:{{name}}</p>
<p>年龄:{{age}}</p>
<p>已婚:{{merried}}</p>
<p>自我介绍:{{info}}</p>
输出内容为:
姓名:李四
年龄:18
已婚:false
自我介绍:我叫李四,今年18岁,未婚。
修改状态数据
直接修改 state
字段
const person = usePerson();
person.age++;
person.merried = true;
最简单的方式。
使用 $patch
传入对象
const person = usePerson();
person.$patch({
age: 30,
merried: true
})
适合批量修改多个数据。
使用 $patch
传入函数
const person = usePerson();
person.$patch((state) => {
state.age++;
state.merried = state.age > 30 ? true : false;
})
适合处理复杂的数据逻辑。
使用 actions
修改数据
actions: {
growUp() {
this.age++;
this.merried = this.age >= 30 ? true : false;
}
}
适合处理复杂的数据逻辑,能更好的与组件解耦
使用 $reset
还原数据
person.$reset();
Getters
不带参数
getters类似vue中的computed属性,我们写一个带*号的电话号码
state: () => {
return {
phone: 18202810831
}
},
getters: {
phoneHidden(state) {
return state.phone.toString().replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2');
}
},
带参数
我们也可以改造一下 phoneHidden
接收一个 isHide
参数。
getters: {
phoneHidden(state) {
return (isHide) => {
if (isHide) {
return state.phone.toString().replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2');
} else {
return state.phone.toString();
}
}
}
},
使用
<p>电话:{{phoneHidden(true)}}</p>
<p>电话:{{phoneHidden(false)}}</p>
输出结果
182****0831
18202810831
store互相调用
我们再创建一个名为 school
的 store
import { defineStore } from "pinia";
export const useSchool = defineStore('school', {
state: () => {
return {
list: []
}
},
actions: {
addStudent(person) {
this.list.push(person);
}
}
})
然后再给 person
的 actions
添加一个 inSchool
方法
import { useSchool } from './school';
...
actions: {
inSchool() {
const school = useSchool();
school.addStudent(this);
}
}
调用 inSchool
方法后,school
里面的 list
里面就会多一条数据。
这样我们就实现了store间的调用。
插件
我们添加一个监视器插件,每当有数据修改的时候,告知我们
import { createPinia } from 'pinia';
const pinia = createPinia();
pinia.use(({state}) => {
store.$subscribe((mutations, state) => {
console.log('属性修改了', state);
})
store.$onAction((action) => {
console.log(action.name, '方法触发了')
})
});