阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > Pinia核心概念(store/state/getters/actions)

Pinia核心概念(store/state/getters/actions)

作者:陈川 阅读数:2854人阅读 分类: Vue.js

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有四种主要方式:

  1. 直接修改(仅组合式API)
const store = useStore()
store.count++
  1. 通过$patch批量更新
store.$patch({
  count: store.count + 1,
  name: 'Bob'
})

// 或使用函数形式
store.$patch((state) => {
  state.items.push({ id: 1 })
  state.hasChanged = true
})
  1. 替换整个state
store.$state = { count: 10, name: 'Charlie' }
  1. 通过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
  }
})

性能优化

  1. 避免在getters中进行昂贵计算:
// 不推荐
getters: {
  heavyComputation() {
    return bigData.value.filter(/* 复杂计算 */)
  }
}

// 推荐使用computed缓存
const heavyComputation = computed(() => {
  return bigData.value.filter(/* 复杂计算 */)
})
  1. 批量更新使用$patch
// 低效
store.name = 'Alice'
store.age = 25
store.role = 'admin'

// 高效
store.$patch({
  name: 'Alice',
  age: 25,
  role: 'admin'
})
  1. 大型应用按功能拆分store:
stores/
├── auth.store.js
├── cart.store.js
├── product.store.js
└── user.store.js

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌