搜索文档
介绍
- Pinia 一个全新的 Vue 状态管理工具。
- Pinia 是下一代的 Vuex,可以取代 Vuex。
- 官网:https://pinia.vuejs.org/zh/
- Vue2 和 Vue3 都支持,更倾向于 Vue3。
- 支持浏览器的 VueDevTools 调试工具。
- 支持模块化热更新。
- 支持使用插件扩展。
核心概念
- Pinia 开发思想于 Vuex 差不多,比 Vuex 更简单。
- Vuex 中核心概念有 4 个:State、Getters、Actions、Mutations。
- Pinia 中核心概念有 3 个:State、Getters、Actions。
- Vuex 中的 Actions 只能异步处理逻辑,在 Pinia 中 Actions 既可以异步也可以同步。
快速上手
安装
sh
npm i pinia入口文件
js
import { createApp } from 'vue';
import App from './App.vue';
import { createPinia } from 'pinia';
const app = createApp(App);
app.use(createPinia()); // createPinia 用于创建 Pinia 实例
app.mount('#app');容器代码
js
import { defineStore } from "pinia";
/**
* 定义并导出容器
* 参数1:容器 ID,必须唯一
* 参数2: 选项对象
* 返回值是一个函数,调用函数返回容器实例
*/
export const UserStore = defineStore('user', {
/**
* 数据容器,类似于组件的 data
* 必须是箭头函数
*/
state: () => ({
count: 100,
total: 20
}),
/**
* 类似于组件的 computed,用来封装计算属性,有缓存功能
*/
getters: {},
/**
* 类似于组件的 methods,用来处理业务逻辑
* 内部不能写箭头函数,this 指向会变
*/
actions: {}
})组件中使用
vue
<template>
<h3>count: {{ count }}</h3>
<h3>total: {{ total }}</h3>
</template>
<script setup>
import { storeToRefs } from "pinia";
import { UserStore } from "./store";
let { count, total } = storeToRefs(UserStore());
</script>修改容器中的数据
准备组件及容器
vue
<template>
<h3>姓名: {{ name }}</h3>
<h3>年龄: {{ age }}</h3>
<h3>爱好: {{ hobby }}</h3>
<button @click="changeInfo">修改信息</button>
</template>
<script setup>
import { storeToRefs } from "pinia";
import { UserStore } from "./store";
const store = UserStore();
const changeInfo = () => {
}
let { name, age, hobby } = storeToRefs(store);
</script>js
import { defineStore } from "pinia";
export const UserStore = defineStore('user', {
state: () => ({
name: 'iGma',
age: 20,
hobby: []
})
})方式一:直接修改
js
const store = UserStore();
const changeInfo = () => {
store.name += '~';
store.age += 10;
store.hobby.push(10);
}方式二:$patch 批量更新
js
const store = UserStore();
const changeInfo = () => {
store.$patch({
name: store.name += '~',
age: store.age += 10,
hobby: [...store.hobby, 10]
})
}方式三:$patch 函数
js
const store = UserStore();
const changeInfo = () => {
store.$patch(state => {
state.name += '~';
state.age += 10;
state.hobby.push(10);
})
}方式四:在 Actions 中封装方法
js
const store = UserStore();
const changeInfo = () => {
store.updateState();
}js
import { defineStore } from "pinia";
export const UserStore = defineStore('user', {
state: () => ({
name: 'iGma',
age: 20,
hobby: []
}),
actions: {
updateState() {
this.name += '~';
this.age += 10;
this.hobby.push(10);
}
}
})getter 用法
和 Vuex 一样,用的不多。
vue
<template>
<h3>姓名: {{ name }}</h3>
<h3>年龄: {{ age }}</h3>
<h3>爱好: {{ hobby }}</h3>
<h3>爱好和: {{ sumHobby }}</h3>
<button @click="changeInfo">修改信息</button>
</template>
<script setup>
import { storeToRefs } from "pinia";
import { UserStore } from "./store";
const store = UserStore();
const changeInfo = () => {
store.updateState();
}
let { name, age, hobby, sumHobby } = storeToRefs(store);
</script>js
import { defineStore } from "pinia";
export const UserStore = defineStore('user', {
state: () => ({
name: 'iGma',
age: 20,
hobby: []
}),
actions: {
updateState() {
this.hobby.push(10);
}
},
getters: {
sumHobby() {
let sum = 0;
this.hobby.forEach(item => {
sum += item;
})
return sum;
}
}
})storeToRefs 用法
假设某个 pinia 身上有很多数据,这是我们想在组件中结构赋值并保证数据的响应式建议使用 Pinia 提供的 storeToRefs 而不是 Vue3 提供的 toRefs
js
import { defineStore } from "pinia";
export const UserStore = defineStore('user', {
state: () => ({
name: 'iGma',
age: 20,
hobby: []
}),
})vue
<script setup>
import { storeToRefs } from "pinia";
import { UserStore } from "./store";
const store = UserStore();
let { name, age, hobby } = storeToRefs(store);
</script>$subscribe
当我们创建一个 Pinia 实例对象时,可以使用对象身上的 $subscribe 方法监听数据的变化。
vue
<script setup lang="ts">
import {userStore} from '@/pinia/user';
import {storeToRefs} from "pinia";
let user = userStore();
let {name, age, gender} = storeToRefs(user);
function changeAge() {
user.age += 1;
}
user.$subscribe((mutation, state) => {
console.log('mutation', mutation);
console.log('state', state);
})
</script>
<template>
<p>用户名:{{name}}</p>
<p>年龄:{{age}}</p>
<p>性别:{{gender}}</p>
<button @click="changeAge">修改年龄</button>
</template>