一、介绍
相同点: 都是Vue.js的状态管理工具
不同点:
区别 | Pinia | Vuex |
---|---|---|
支持 | Vue2和Vue3都支持 | Vue3写法需要额外配置 |
Mutation | 只有 state, getter 和 action,无Mutation | action异步、Mutation 同步 |
action | action支持同步和异步 | action异步、Mutation 同步 |
Typescript | 良好的Typescript支持 | 需要额外的配置 |
模块嵌套 | 不需要嵌套模块,符合 Vue3 的 Composition api,让代码扁平化 | 需要 |
模块嵌套 | 不需要嵌套模块,符合 Vue3 的 Composition api,让代码扁平化 | Vuex中如果数据过多,我们通常分模块来进行管理 |
模块嵌套 | 不需要嵌套模块,符合 Vue3 的 Composition api,让代码扁平化,pinia中每个store都是独立的,互相不影响 | Vuex中如果数据过多,我们通常分模块来进行管理 |
体积 | 体积非常小,只有1KB左右 | 体积大 |
插件扩展 | 支持插件来扩展自身功能 | 不能 |
服务端渲染 | 支持服务端渲染 | 不能 |
总结:pinia的优点
- 支持Vue3 和 Vue2,完整的 ts 的支持;
- 足够轻量,压缩后的体积只有1kb左右;
- 去除 mutations,只有 state,getters,actions;
- actions 支持同步和异步;
- 代码扁平化没有模块嵌套,只有 store 的概念,store 之间可以自由使用,每一个store都是独立的 无需手动添加store,store 一旦创建便会自动添加;
- 支持插件来扩展自身功能|
- 支持服务端渲染
注意点
pina的使用,有时候动态路由一般需要在beforeEach中去做拦截处理,把后端传过来的路由数据存入,页面第一次也会去走一次router文件,由于pinia没有挂载到vue上面,导致报错,
问题: Uncaught Error: [🍍]: getActivePinia was called with no active Pinia. Did you forget to install pinia?
这个问题代表当前正在使用pinia; 但是pinia 还没有挂载成功
做法就是新建一个js文件,然后在js文件创建初始化,然后导出,然后分别在main和使用路由守卫的地方去引入。
二、使用
1、pinia使用
- 安装
npm install pinia@next
- vue3项目下创建一个 Pinia store,例如counterStore.js
import { defineStore } from 'pinia';
export const useCounterStore = defineStore({
id: 'counter',
state: () => ({
count: 0,
}),
getters: {
doubleCount() {
return this.count * 2;
},
},
actions: {
increment() {
this.count++;
},
decrement() {
this.count--;
},
},
});
- 引入 Pinia 到 Vue 应用中
// main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const app = createApp(App)
const pinia = createPinia()
app.use(pinia)
app.mount('#app')
- 在页面上使用
<template>
<div>
<p>Count: {{ counter.count }}</p>
<p>Double Count: {{ counter.doubleCount }}</p>
<button @click="counter.increment">Increment</button>
<button @click="counter.decrement">Decrement</button>
</div>
</template>
<script>
import { useCounterStore } from '@/counterStore.js';
export default {
setup() {
const counter = useCounterStore();
return { counter };
},
};
</script>
2、Vuex使用
- 安装
npm install vuex
- Vue 2 项目中创建一个 Vuex store,例如 store.js 的文件
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
count: 0,
},
mutations: {
increment(state) {
state.count++;
},
decrement(state) {
state.count--;
},
},
actions: {
increment(context) {
context.commit('increment');
},
decrement(context) {
context.commit('decrement');
},
},
getters: {
doubleCount(state) {
return state.count * 2;
},
},
});
- 主Vue实例中引入并配置store。
// main.js
import Vue from 'vue';
import App from './App.vue';
import store from './store';
new Vue({
store,
render: h => h(App)
}).$mount('#app');
- 在页面上使用
<template>
<div>
<p>Count: {{ $store.state.count }}</p>
<p>Double Count: {{ doubleCount }}</p>
<button @click="increment">Increment</button>
<button @click="decrement">Decrement</button>
</div>
</template>
<script>
export default {
computed: {
doubleCount() {
return this.$store.getters.doubleCount;
},
},
methods: {
increment() {
this.$store.dispatch('increment');
},
decrement() {
this.$store.dispatch('decrement');
},
},
};
</script>
- 优化,有时候需要引入很多个,此时可以根据自动批量导入JS模块
import Vue from 'vue'
import Vuex from 'vuex';
Vue.use(Vuex);
//导入modules所有模块
const modulesFiles = require.context('./modules', true, /\.js$/);
const modules={};
modulesFiles.keys().forEach(key => {
const module= modulesFiles(key).default;
const moduleName=key.slice(2,-3);//以文件名为模块名,./user.js 截取(user)
modules[moduleName]=module
});
const store=new Vuex.Store({
modules,
});
export default store
- 例如user.js的写法
const state = {
name: '测试'
};
const getters = {
getName: state => state.name
}
const mutations = {
SET_NAME(state, val) {
state.name = val;
}
};
const actions = {
setName({commit}, val) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('SET_NAME', val);
resolve()
}, 100)
}).catch(err => {
reject(err)
})
}
};
export default {
namespaced: true,
state,
mutations,
actions,
getters
};
- 自动批量导入JS模块:在页面上使用
export default {
mounted(){
获取user state里面的数据
this.$store.state.user.name //测试
修改user mutations 的数据
this.$store.commit(‘user/SET_NAME’,‘修改’)
获取user getters
this.$store.getters[‘user/getName’]
异步修改state里面的数据
await this.$store.dispatch(‘user/setName’,‘修改’)
}
}