vuex和pinia转态管理工具介绍

本文比较了Pinia和Vuex在Vue.js中的应用,强调了Pinia对Vue3的支持、TypeScript集成、轻量级设计、无Mutation等优点,同时提到了Vuex的模块管理和异步处理。还讨论了Pinia的使用注意事项,包括动态路由拦截和初始化问题。
摘要由CSDN通过智能技术生成

一、介绍

相同点: 都是Vue.js的状态管理工具

不同点:

区别PiniaVuex
支持Vue2和Vue3都支持Vue3写法需要额外配置
Mutation只有 state, getter 和 action,无Mutationaction异步、Mutation 同步
actionaction支持同步和异步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’,‘修改’)
  }		
}

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Smile_zxx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值