从 Vuex 迁移:Migrating from Vuex ≤4
其实在使用上区别不大,但是有几点需要改变:
Vuex 如何使用 actions
?Pinia 这里做了两点改变
第一个参数 context
被移除
// vuex index.js
import appModule from './modules/app
const store = createStore({
modules: {
appModule
}
})
// vuex modules/app.js
const useAppStore = createStore({
state: {
count: 0
},
mutations: {
increment (state, num) {
state.count += num
}
},
actions: {
increment (context, num) {
// 或是直接把 context 里的 commit 解构出来
context.commit('increment', num)
}
}
})
不再使用 dispatch
调用 actions
// .vue 文件
this.$store.dispatch('app/increment', 2)
Pinia 如何使用 actions
?
actions
里直接使用 this 获取到 state
的值// pinia modules/app.js
const useAppStore = defineStore('app', {
state: {
count: 0
},
actions: {
increment (num) {
this.state.count += num
}
}
})
// .vue 文件
import useAppStore from '@/store/modules/app'
useAppStore().increment(2)
# Vuex
src
└── store
├── index.js
└── modules
├── module1.js
└── nested
├── index.js
├── module2.js
└── module3.js
# Pinia
src
└── stores
├── index.js
├── module1.js
├── nested-module2.js
├── nested-module3.js
└── nested.js
Vuex 需要有一个主要的 Store
,最终会形成一个树形引用结构
Pinia 不再需要一个主要的 Store
,是一个平面的结构,可创建不同的 Store
const useAppStore = defineStore('app', { /* ... */ })
namespaced: true
) import appModule from './modules/app
const store = createStore({
modules: {
appModule
}
})
// vuex modules/app.js
const useAppStore = createStore({
namespaced: true
})
Vuex 里一个 getters
想使用其他 getters
,需要借助其第二个参数
const useBookStore = createStore({
state() {
return {
books: [
{ name: 'book1', count: 3, price: 10 },
{ name: 'book2', count: 1, price: 20 },
{ name: 'book3', count: 2, price: 15 }
],
discount: 0.9
}
},
getters: {
totalPrice(state, getters) {
const totalPrice = state.books.reduce((acc, cur) => {
return (acc += cur.count * cur.price)
}, 0)
return totalPrice * getters.currentDiscount
},
currentDiscount(state) {
return state.discount
}
}
}
Pinia 去掉了第二个参数,可以在里面使用 this 取到其他 getters
const useBookStore = createStore({
state() {
return {
books: [
{ name: 'book1', count: 3, price: 10 },
{ name: 'book2', count: 1, price: 20 },
{ name: 'book3', count: 2, price: 15 }
],
discount: 0.9
}
},
getters: {
totalPrice(state) {
const totalPrice = state.books.reduce((acc, cur) => {
return (acc += cur.count * cur.price)
}, 0)
return totalPrice * this.currentDiscount
},
currentDiscount(state) {
return state.discount
}
}
})
这里补充一点:由于 getters
是无法接受参数的,如果想要接受参数可以使用闭包
const useBookStore = createStore({
getters: {
totalPriceGreaterN(state, getters) {
return n => {
let totalPrice = 0
const totalPrice = state.books.reduce((acc, cur) => {
if (cur.count > n) {
return (acc += cur.count * cur.price)
} else {
return acc
}
}, 0)
return totalPrice * getters.currentDiscount
}
}
}
}
在模板中可以这样使用(只是单方面举例)
<h2>{{ $store.getters.totalPriceGreaterN(2) }}h2>