大家好,我是右子。
Vue3
成为默认版后,Vuex
的状态管理地位受到了Pinia
的挑战。
推荐使用Pinia
,因为Pinia
确实太方便和简单了。
分享内容
- Pinia的优势和安装
- 使用Pinia的方式创建store和读取
- 用简单的方法改变状态数据
- Pinia改变状态数据的几种方式
- Pinia中Actions的使用
- Pinia中Getters的使用
Pinia的优势
Pinia是Vue生态里Vuex的代替者,是新一代Vue的状态管理库。
- 可以对Vue2和Vue3做到很好的支持,也就是老项目也可以使用Pinia。
- 抛弃了
Mutations
的操作,只有state、getters和actions,极大的简化了状态管理库的使用,让代码编写更加容易直观。 - 不需要嵌套模块,符合Vue3的
Composition api
,让代码更加扁平化。 - 完整的TypeScript支持,Vue3版本的一大优势就是对TypeScript的支持,所以Pinia也做到了完整的支持。
- 代码更加简洁,可以实现很好的代码自动分割。在Vue2中写代码需要来回翻滚屏幕屏幕找变量,非常的麻烦,Vue3的Composition api完美了解决这个问题。 可以实现代码自动分割,pinia也同样继承了这个优点。
简单总结Pinia的优势就是,更加简洁的语法,完美支持Vue3的Composition api 和 对TypesCcript的完美支持。这些优势和尤雨溪的强烈推荐,个人觉得 Pinia 将成为最适合Vue3的状态管理库。
Pinia 的安装
安装Pinia状态管理库了。安装的方法依然是使用npm
来安装。
npm install pinia
# or with pnpm
pnpm install pinia
视频中使用了npm
来进行安装。安装完成后,可以到项目中的package.json
文件中查看一下pinia的版本。
{
"name": "pinia-cli",
"version": "1.0.0",
"scripts": {
},
"dependencies": {
"pinia": "^2.0.13"
}
}
你也可以指定pinia的安装版本,比如2.0.13
。
npm install pinia@2.0.13
引用Pinia
我们使用 import
引入。
// main.js
import { createPinia } from 'pinia';
引入后,通过 createPinia()
方法,得到pinia的实例和挂载到Vue根实例上。
// main.js
import { createApp } from 'vue';
import { createPinia } from 'pinia' ;
import App from './App.vue';
// 创建pinia 实例
const pinia = createPinia();
const app = createApp(App);
// 挂载到 Vue 根实例上
app.use(pinia);
app.mount('#root');
这样我们就在项目中引入了Pinia
,也就是说我们可以在项目中使用它进行编程了。
创建store状态管理模块
引入Pinia后,就可以创建状态管理库了,也就是常说的Store
。新建一个store
文件夹,在文件夹内创建一个index.js
文件,一般我们只做三件事。
- 定义状态(state:()=> {})
- 修改容器中的 state
- 仓库中的
action
的使用
明确了之后,我们来编写代码。
import { defineStore } from 'pinia';
export const mainStore = defineStore('main',{
state(){
return {};
},
getters:{},
actions:{}
});
写完这段代码,你会感觉这个很像一个Vue的组件,这也算是Pinia的一个优点。
defineStore()
方法的第一个参数:相当于为容器起一个名字。- 注意:这里的名字必须唯一,不能重复。
defineStore()
方法的第二个参数:可以简单理解为一个配置对象,里边是对store仓库的配置说明。state
:用来存储全局的状态的,这里边定义的,就可以是为SPA里全局的状态了。getters
:用来监视或者说是计算状态的变化的,有缓存的功能。actions
:对state里数据变化的业务逻辑,需求不同,编写逻辑不同。
我们在Store里定义一个State,我们这里就写hi Pinia.
。
const store = {
state:()=>{
return {
projectName:'hi Pinia.',
count: 0
}
}
}
这时候这个hi Pinia.
就是全局的状态数据,是每个页面和组件都可以通过Pinia方法读取到的。
读取store中的数据
<template>
<div>{{ store.projectName }}</div>
</template>
<script setup>
import { mainStore } from "@app/stores/index";
const store = mainStore();
console.log(store);
</script>
先引入mainStore
,然后通过mainStore
得到store
实例,就可以在组件里调用store里定义的state
数据状态了。
修改store中的数据
首先我们读取出数据,然后添加一个事件操作。
<template>
<div>计数器:{{ store.count }}</div>
<button @click="onCount"></button>
</template>
<script setup>
import { mainStore } from "@app/stores/index";
const store = mainStore();
console.log(store);
function onCount(){
store.count = store.count+1;
};
</script>
看!这种改变状态数据的方法是非常方便的,要比Vuex
简洁多了。可以看到当你点击按钮后,数据通过Pinia的状态管理,已经响应到页面中了。
结构的store数据还是响应式的吗?
当你结构了store,数据就不是响应式的了,但是有方法可以解决。
import { storeToRefs } from "pinia"; // pinia提供的响应式方法
import { mainStore } from "@app/stores/index";
const { count } = storeToRefs(mainStore());
console.log(store);
function onCount(){
count = count+1;
};
使用 $patch
修改数据
如果你同时修改多条数据,建议使用$patch
的方法。
<template>
<div>计数:{{ store.count }}</div>
<div>项目名:{{ store.projectName }}</div>
<button @click="onChange"></button>
</template>
<script setup>
import { mainStore } from "@app/stores/index";
const store = mainStore();
function onChange(){
store.$patch({
count: store.count + 1,
projectName: store.projectName + '!'
});
};
</script>
$patch
可以传入一个对象作为参数,也可以传入一个函数作为参数使用,可以处理一些复杂的逻辑。
<template>
<div>计数:{{ store.count }}</div>
<div>项目名:{{ store.projectName }}</div>
<button @click="onChange"></button>
</template>
<script setup>
import { mainStore } from "@app/stores/index";
const store = mainStore();
function onChange(){
store.$patch((state)=>{
state.count ++;
state.projectName = state.projectName + '!';
});
};
</script>
使用 actions
方法
还可以使用actions
中定义函数处理数据,然后在组件里调用函数。
// path => store/index.js
import { defineStore } from 'pinia';
export const mainStore = defineStore('main',{
state(){
return {
count: 0,
projectName: "hi Pinia."
};
},
getters:{},
actions:{
setStateChange(){
this.count ++;
this.projectName = "hi Pinia...";
}
}
});
// path => app.vue
<template>
<div>计数:{{ store.count }}</div>
<div>项目名:{{ store.projectName }}</div>
<button @click="onChange"></button>
</template>
<script setup>
import { mainStore } from "@app/stores/index";
const store = mainStore();
function onChange(){
store.setStateChange();
};
</script>
使用 getterrs
方法
在getters里面编写一个方法,处理数据。
import { defineStore } from 'pinia';
export const mainStore = defineStore('main',{
state(){
return {
count: 0,
projectName: "hi Pinia."
};
},
getters:{
handlerCount(state){
return state.projectName = "hello, new state management tools";
}
},
actions:{}
});
<template>
<div>计数:{{ store.handlerCount }}</div>
<button @click="onChange"></button>
</template>
<script setup>
import { mainStore } from "@app/stores/index";
const store = mainStore();
function onChange(){
store.count ++;
};
</script>
Pinia中的getters
是有缓存特性的。
当数据改变时,getters会自动工作,对应的方法也会随着调用一次,清除以前的数据缓存。
总结
以上就是Pinia的使用方法,具体还可以参考Pinia官网进行学习。