https://pinia.vuejs.org/zh/introduction.html
Pinia和Vuex都是Vue.js状态管理库,但它们在一些方面有所不同。
Pinia是一个轻量级的状态管理库,它专注于提供一个简单的API来管理应用程序的状态。相比之下,Vuex是一个更完整的状态管理库,它提供了更多的功能,比如模块化、插件和严格模式等。
Pinia是基于Vue 3的Composition API构建的,这使得它更加灵活和可组合。而Vuex则是基于Vue 2的Options API构建的,因此在某些方面可能会受到限制。
Pinia采用了类似于React Hooks的方式来管理状态,这使得它更加直观和易于使用。Vuex则采用了一种基于mutations和actions的方式来管理状态,这可能需要更多的代码来实现相同的功能。
Pinia 和 Vuex 都有其优点和缺点。
优点
Pinia 的优点: 1. 更加轻量级:相比 Vuex,Pinia 更加轻量级,因为它不需要使用 Vuex 的一些复杂的概念,如模块和 getter。 2. 更加简单易用:Pinia 的 API 设计更加简单易用,因为它使用了 Vue.js 3 的新特性,如 Composition API。 3. 更加灵活:Pinia 提供了更加灵活的状态管理方式,因为它支持多个 store 实例,而 Vuex 只支持一个 store 实例。
Vuex 的优点: 1. 更加成熟:Vuex 是一个比较成熟的状态管理库,它已经被广泛使用和测试。 2. 更加稳定:Vuex 的稳定性也比 Pinia 更高,因为它已经经过了多个版本的迭代和改进。 3. 更加强大:Vuex 提供了一些高级功能,如中间件和插件,使得它可以处理更加复杂的状态管理需求。
缺点:
Pinia 的缺点: 1. 相对较新:Pinia 是一个相对较新的状态管理库,因此它可能存在一些未知的问题和限制。 2. 生态系统不够完善:由于 Pinia 是一个相对较新的库,它的生态系统可能不够完善,因此可能需要花费更多的时间来解决问题。
Vuex 的缺点: 1. 学习曲线较陡峭:Vuex 的概念比较复杂,因此学习曲线比较陡峭。 2. 繁琐:Vuex 在处理一些简单的状态管理需求时可能会有些繁琐,因为它需要使用一些复杂的概念和 API。
总的来说,Pinia适合那些想要一个简单、轻量级的状态管理库的开发者,而Vuex则适合那些需要更多功能和灵活性的开发者。
yarn add pinia
// 或者使用 npm
npm install pinia
main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const pinia = createPinia()
createApp(App).use(pinia).mount('#app') // vue3 的简写语法
在 src 文件中,创建 store 文件,里面按模块创建 ts 文件(也可以是 js)。
注意: pinia 不需要创建 modules 文件来区分模块化,这是它和 vuex 的区别。
store/user.ts:
// 你可以任意命名 defineStore()
的返回值,但最好使用 store 的名字,同时以 use
开头且以 Store
结尾。 (比如 useUserStore
,useCartStore
,useProductStore
)
// Store 是用 defineStore() 定义的,它的第一个参数要求是一个独一无二的名字,也被用作 id ,是必须传入的。
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
userInfo: {}
}),
actions: {
SetUserInfo(data: any) {
this.userInfo = data
}
}
})
先引入模块,再将引入的模块对象赋值给变量 store (命名随意),如果不需要修改数据,用 const 声明变量,需要修改数据则使用 let 声明。
注意:引入的模块对象名要与模块中 export const 声明的一致。
xx.ts or xx.vue:
import { useUserStore } from '@/store/user'
const store: any = useUserStore()
console.log(store.userInfo)
修改数据多种方法,可以直接修改,也可以使用 actions 修改。
xx.ts or xx.vue:
import { useUserStore } from '@/store/user'
const store = useUserStore()
store.userInfo = obj // obj 指新值
xx.ts or xx.vue:
import { useUserStore } from '@/store/user'
const store = useUserStore()
store.SetUserInfo(obj) // obj 指新值
store/user.ts:
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
name: null,
age: null,
sex: null,
}),
})
上面的方法都是用来修改单个属性的,如果你需要一次修改多个属性,虽然你可以重复操作上面的方法,但是 pinia 提供了新的方法:store.$patch
xx.ts or xx.vue:
import { useUserStore } from '@/store/user'
const store = useUserStore()
// 你可以这样去修改(不建议)
store.name = '张三'
store.age = 24
store.sex = '男'
// 推荐使用下面这种方式 √
store.$patch({
name: '张三',
age: 24,
sex: '男',
})
定义数据
Getter计算属性,相当于computed。可以通过 defineStore() 中的 getters 属性来定义它们。推荐使用箭头函数,并且它将接收 state 作为第一个参数:
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
getters: {
// 自动推断出返回类型是一个 number
doubleCount(state) {
return state.count * 2
},
// 返回类型**必须**明确设置
doublePlusOne(): number {
// 整个 store 的 自动补全和类型标注 ✨
return this.doubleCount + 1
},
},
})
使用:
Double count is {{ store.doubleCount }}
Action 相当于组件中的 method。它们可以通过 defineStore() 中的 actions 属性来定义,并且它们也是定义业务逻辑的完美选择。
export const useCounterStore = defineStore('main', {
state: () => ({
count: 0,
}),
actions: {
increment() {
this.count++
},
randomizeCounter() {
this.count = Math.round(100 * Math.random())
},
},
})
使用: