【vue】状态管理Vuex和pinia区别

100 阅读5分钟

Vuex

1726121587517.png

pinia

image.png

安装

npm i Vuex
npm i Pinia

使用

vuex

  1. 创建Vuex Store
import Vue from 'vue'
import Vuex from 'vuex' 
Vue.use(Vuex) 
export default 
new Vuex.Store({ 
    state: {}, 
    mutations: {}, 
    actions: {}, 
    getters: {}
})

2、创建外部JavaScript文件

export const state = () => ({ 
count: 0 
})
export const mutations = { 
increment(state) {
state.count++ 
}
} 
export const actions = {
incrementIfOddOnRootSum({
state, commit, rootState 
})
{
if ((state.count + rootState.otherCount) % 2 === 1)
{ commit('increment') }
} 
}
export const getters = {
doubleCount(state) { return state.count * 2 }
}
  1. 在Vuex Store中引入外部JavaScript文件 你可以在你的Vuex store中引入并使用这些外部文件了。如果你想要将上面的example.js作为模块引入,你可以这样做:
	import Vue from 'vue'  
	import Vuex from 'vuex'  
	import { state, mutations, actions, getters } from './modules/example'  
	Vue.use(Vuex)  
	export default new Vuex.Store({  
	  modules: {  
	    example: {  
	      namespaced: true,  
	      state,  
	      mutations,  
	      actions,  
	      getters  
	    }  
	  }  
	})

pinia

  1. 创建Pinia Store
	import { createApp } from 'vue'  
	import { createPinia } from 'pinia'  
	import App from './App.vue'  
	const app = createApp(App)  
	// 创建Pinia实例并安装到Vue应用中  
	const pinia = createPinia()  
	app.use(pinia)  
	app.mount('#app')
  1. 创建外部JavaScript文件(Pinia Store)
	import { defineStore } from 'pinia'  
	export const useExampleStore = defineStore('example', {  
	  state: () => ({  
	    count: 0  
	  }),  
	  actions: {  
	    increment() {  
	      this.count++  
	    }  
	  },  
	  getters: {  
	    doubleCount: (state) => state.count * 2  
	  }  
	})
  1. 在组件中引入并使用Pinia Store 你可以在任何Vue组件中引入并使用这个Pinia store了。
	<template>  
	  <div>  
	    <p>Count: {{ count }}</p>  
	    <p>Double Count: {{ doubleCount }}</p>  
	    <button @click="increment">Increment</button>  
	  </div>  
	</template>  
	<script>  
	// 引入Pinia store  
	import { useExampleStore } from '../stores/example'  
	export default {  
	  setup() {  
	    const store = useExampleStore()  
	    // 使用store中的state和actions  
	    const count = computed(() => store.count)  
	    const doubleCount = computed(() => store.doubleCount)  
	    function increment() {  
	      store.increment()  
	    }  
	    // 返回给模板使用的响应式数据和方法  
	    return { count, doubleCount, increment }  
	  }  
	}  
	</script>

Vuex和Pinia都是Vue.js的状态管理工具,它们在多个方面存在显著的差异。

代码风格和语法区别

vuexstategettersmutationsactions

1. state state是Vuex中的核心,它用于存储应用的响应式数据。在Vuex中,state是一个对象,你可以在这个对象中定义需要管理的状态。Vue组件可以从store中读取状态,并且当状态发生变化时,组件会重新渲染。

	const store = new Vuex.Store({  
	  state: {  
	    count: 0  
	  }  
	})

2. getters

getters允许你从store中派生出一些状态,这些状态依赖于state中的值,但又不直接修改state。它们类似于Vue组件中的计算属性。你可以在getters中定义一些方法,这些方法接收state作为参数,并返回一个新的值。

	const store = new Vuex.Store({  
	  state: {  
	    count: 0  
	  },  
	  getters: {  
	    doubleCount: state => state.count * 2  
	  }  
	})

3. mutations

mutations是Vuex中唯一允许更新state的方法。由于Vuex的设计原则之一是确保状态变化的可预测性,因此它要求所有的状态更新都必须通过提交mutation来完成。mutation是一个同步函数,它接收state作为第一个参数,并可以接收额外的参数作为负载(payload)。

	const store = new Vuex.Store({  
	  state: {  
	    count: 0  
	  },  
           getters: {  
	    doubleCount: state => state.count * 2  
	   },
	  mutations: {  
	    increment(state) {  
	      state.count++  
	    }  
	  }  
	})

在组件中,通过this.$store.commit方法来提交一个mutation

4. actions

actions类似于mutations,但它可以包含任意异步操作。在actions中,你可以通过context.commit来提交一个mutation,或者通过context.statecontext.getters来访问stategettersactions的主要目的是处理应用中可能发生的异步事件。

	const store = new Vuex.Store({  
	  state: {  
	    count: 0  
	  },  
	  mutations: {  
	    increment(state) {  
	      state.count++  
	    }  
	  },  
           getters: {  
	    doubleCount: state => state.count * 2  
	  },
	  actions: {  
	    incrementAsync({ commit }) {  
	      setTimeout(() => {  
	        commit('increment')  
	      }, 1000)  
	    }  
	  }  
	})

在组件中,你可以通过this.$store.dispatch来分发一个action

piniastategettersactions

1. state

state是store中的核心部分,用于存储应用的响应式数据。在Pinia中,state是一个函数,该函数返回一个对象,该对象包含了你想要存储在store中的状态。

	// store.js  
	import { defineStore } from 'pinia'  
	export const useMyStore = defineStore('myStore', {  
	  state: () => ({  
	    count: 0,  
	    name: 'John Doe'  
	  }),  
	  // ... 其他选项  
	})

在组件中,你可以通过storeToRefs或直接在模板中解构来访问state,以保持其响应性。

	<template>  
	  <div>  
	    <p>{{ count }}</p>  
	    <p>{{ name }}</p>  
	  </div>  
	</template>  
	<script>  
	import { useMyStore } from './store'  
	export default {  
	  setup() {  
	    const store = useMyStore()  
	    // 使用storeToRefs来保持响应性(对于复杂状态或需要解构的情况)  
	    // const { count, name } = storeToRefs(store)  
	    // 直接在模板中使用,Vue 3的模板编译器会自动处理响应性  
	    return {  
	      count: store.count,  
	      name: store.name  
	    }  
	  }  
	}  
	</script>

2. getters

getters允许你从state中派生出一些状态,这些状态依赖于state中的值,但又不直接修改state。它们类似于Vue组件中的计算属性。

	// store.js  
	export const useMyStore = defineStore('myStore', {  
	  state: () => ({  
	    count: 0  
	  }),  
	  getters: {  
	    // 使用箭头函数来访问this.count  
	    doubleCount: (state) => state.count * 2,  
	    // 或者使用函数,并通过第一个参数访问state  
	    doubleCountAlt(state) {  
	      return state.count * 2  
	    }  
	  },  
	  // ... 其他选项  
	})

在组件中,你可以像访问state一样访问getters

3. actions

actions是包含任意异步逻辑的函数,用于执行副作用。它们可以修改state的值,但通常用于执行异步操作或复杂的逻辑,这些逻辑可能需要访问stategetters或其他actions

	// store.js  
	export const useMyStore = defineStore('myStore', {  
	  state: () => ({  
	    count: 0  
	  }),  
	  actions: {  
	    increment() {  
	      this.count++  
	    },  
	    incrementAsync(delay = 1000) {  
	      setTimeout(() => {  
	        this.increment()  
	      }, delay)  
	    }  
	  },  
	  // ... 其他选项  
	})

以下是它们之间主要区别的详细分析:

  1. 设计理念和使用方式

Vuex:采用了集中式的架构,通过一个全局的store对象来管理所有状态。组件通过访问这个store对象来获取和修改状态。(使用Object.defineProperty来实现数据的响应式)

Pinia:Pinia是专为Vue3设计的状态管理库,采用了去中心化的架构,每个组件或模块拥有自己的store实例。Pinia的API设计更加简单直观,与Vue 3的Composition API紧密集成,提供了更好的开发体验。Pinia使用Vue 3的Proxy代理机制来实现数据的响应式,具有更好的性能和功能。

  1. 体积和复杂性

Vuex:复杂性和功能相对较多,包括模块化、插件和严格模式等。

Pinia:Pinia是一个相对较新的库,它更加轻量级和简单。Pinia的体积较小(约1KB),减少了不必要的复杂性和概念。

3.TypeScript 支持

Vuex:Vuex从Vue 2.x版本开始引入了对TypeScript的支持,但需要使用额外的插件或手动注解来实现类型检查。

Pinia:Pinia在设计之初就对TypeScript提供了原生的支持,提供了更好的类型推导和类型检查的支持。这使得在Pinia中使用TypeScript时能够更容易地捕获错误和进行静态类型检查。
4. 代码风格和语法

Vuex:Vuex使用了stategettersmutationsactions的方式来修改和处理状态。组件需要通过dispatch或commit来触发mutations或actions中的方法,以实现对状态的修改。

Pinia:Pinia更加倾向于直接操作状态,它提供了stategettersactions等属性来定义和管理状态。在Pinia中,可以直接通过修改state来更新状态,而getters用于计算派生状态,actions则用于执行异步操作或复杂的逻辑。

  1. 生态系统和插件

Vuex:Vuex拥有较为庞大的生态系统,有许多相关的插件和工具可供选择,如用于处理持久化、路由集成、调试等各种功能的插件。

Pinia:Pinia作为一个相对较新的库,其生态系统相对较小但也在不断发展壮大。目前已有一些插件和工具可供使用,但相比Vuex来说可能还不够完善。