Pinia核心概念(store/state/getters/actions)
Pinia是Vue.js的轻量级状态管理库,提供store、state、getters和actions等核心概念,简化全局状态管理。下面详细解析这些概念的具体用法和实际场景中的最佳实践。
Store
Store是Pinia的核心单元,每个store对应一个独立的状态容器。通过defineStore
函数创建,支持Option API和Setup API两种风格。
// 选项式写法
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
getters: {
double: (state) => state.count * 2
},
actions: {
increment() {
this.count++
}
}
})
// 组合式写法
export const useUserStore = defineStore('user', () => {
const name = ref('Alice')
const age = ref(25)
const isAdult = computed(() => age.value >= 18)
function growUp() {
age.value++
}
return { name, age, isAdult, growUp }
})
Store具有响应式特性,在组件中使用时需要保持引用不变:
// 正确用法
const store = useStore()
// 错误用法(会失去响应性)
const { count } = useStore()
State
State是store的响应式数据源,支持所有JavaScript类型。修改state有四种主要方式:
- 直接修改(仅组合式API)
const store = useStore()
store.count++
- 通过
$patch
批量更新
store.$patch({
count: store.count + 1,
name: 'Bob'
})
// 或使用函数形式
store.$patch((state) => {
state.items.push({ id: 1 })
state.hasChanged = true
})
- 替换整个state
store.$state = { count: 10, name: 'Charlie' }
- 通过actions修改(推荐)
// 在store中定义
actions: {
reset() {
this.$reset() // 重置到初始状态
}
}
Getters
Getters相当于store的计算属性,具有缓存特性。支持通过this
访问整个store实例:
getters: {
// 基本getter
doubleCount: (state) => state.count * 2,
// 使用其他getter
quadrupleCount() {
return this.doubleCount * 2
},
// 带参数的getter
getUserById: (state) => {
return (id) => state.users.find(user => user.id === id)
}
}
在组件中使用getter:
const store = useStore()
// 直接访问
console.log(store.doubleCount)
// 带参数调用
console.log(store.getUserById(101))
Actions
Actions是store的方法,支持同步和异步操作。与Vuex不同,Pinia的actions就是普通函数:
actions: {
async fetchUser(userId) {
try {
this.isLoading = true
const response = await api.getUser(userId)
this.user = response.data
} catch (error) {
this.error = error
} finally {
this.isLoading = false
}
},
// 组合多个action
async fetchUserAndPosts(userId) {
await this.fetchUser(userId)
await this.fetchPosts(userId)
}
}
调用actions时不需要dispatch
,直接调用即可:
const store = useStore()
store.fetchUser(123)
高级用法
订阅状态变化
// 监听整个store
const unsubscribe = store.$subscribe((mutation, state) => {
console.log('变化类型:', mutation.type)
console.log('修改数据:', mutation.payload)
})
// 监听特定state
watch(
() => store.count,
(newVal) => {
console.log('count变化:', newVal)
}
)
插件扩展
创建Pinia插件示例:
function localStoragePlugin(context) {
const key = `pinia-${context.store.$id}`
// 从本地存储恢复状态
const savedState = localStorage.getItem(key)
if (savedState) {
context.store.$patch(JSON.parse(savedState))
}
// 订阅变化
context.store.$subscribe((_, state) => {
localStorage.setItem(key, JSON.stringify(state))
})
}
const pinia = createPinia()
pinia.use(localStoragePlugin)
服务端渲染(SSR)
在Nuxt.js中使用需要特殊处理:
// nuxt.config.js
export default {
modules: ['@pinia/nuxt'],
pinia: {
autoImports: ['defineStore']
}
}
// 使用示例
export const useStore = defineStore('main', {
state: () => ({ counter: 0 }),
hydrate(storeState, initialState) {
storeState.counter = initialState.counter || 42
}
})
性能优化
- 避免在getters中进行昂贵计算:
// 不推荐
getters: {
heavyComputation() {
return bigData.value.filter(/* 复杂计算 */)
}
}
// 推荐使用computed缓存
const heavyComputation = computed(() => {
return bigData.value.filter(/* 复杂计算 */)
})
- 批量更新使用
$patch
:
// 低效
store.name = 'Alice'
store.age = 25
store.role = 'admin'
// 高效
store.$patch({
name: 'Alice',
age: 25,
role: 'admin'
})
- 大型应用按功能拆分store:
stores/
├── auth.store.js
├── cart.store.js
├── product.store.js
└── user.store.js
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:Pinia与Vuex对比
下一篇:陈川的代码茶馆🍵