相同点: 都是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的优点
注意点
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和使用路由守卫的地方去引入。
npm install pinia@next
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--;
},
},
});
// 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>
npm install vuex
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;
},
},
});
// 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>

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
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
};
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’,‘修改’)
}
}