浅谈Pinia(皮尼亚)--为什么vue3推荐使用Pinia

12,827 阅读3分钟

0. 前言

Pinia 是测试 Vuex 下一次迭代的提案

截屏2021-11-15 下午4.08.32.png

Vuex5的提案,相比 vuex3和4有很大的改进

  • 支持options api and composition api
  • 没有mutations
  • 没有嵌套的模块
  • 更好typescript支持
  • 自动化的代码拆分

1. 与Vuex的比较

Pinia 试图尽可能接近 Vuex 的理念。它旨在测试 Vuex 下一次迭代的提案,并且取得了成功,目前有一个针对 Vuex 5 的开放 RFC,其 API 与Pinia 使用的 API 非常相似。请注意,Pinia 的作者 I (Eduardo) 是 Vue.js 核心团队的一员,并积极参与 Router 和 Vuex 等 API 的设计。对这个项目的意图是重新设计使用全局 Store 的体验,同时保持 Vue 平易近人的哲学。让 Pania 的 API 与 Vuex 一样接近,因为它不断向前发展,可以轻松迁移到 Vuex,甚至在未来融合这两个项目。

Pinia API 与 Vuex ≤4 有很大不同,:

  • 没有mutations。mutations被认为是非常冗长的。最初带来了 devtools 集成,但这不再是问题。
  • 不再有模块的嵌套结构。您仍然可以通过在另一个store中导入和使用store来隐式嵌套store,但 Pinia 通过设计提供扁平结构,同时仍然支持store之间的交叉组合方式。您甚至可以拥有store的循环依赖关系。
  • 更好typescript支持。无需创建自定义的复杂包装器来支持 TypeScript,所有内容都是类型化的,并且 API 的设计方式尽可能地利用 TS 类型推断。
  • 不再需要注入、导入函数、调用它们,享受自动补全!
  • 无需动态添加stores,默认情况下它们都是动态的,您甚至不会注意到。请注意,您仍然可以随时手动使用store来注册它,但因为它是自动的,所以您无需担心。
  • 没有命名空间模块。鉴于store的扁平架构,“命名空间”store是其定义方式所固有的,您可以说所有stores都是命名空间的。

2. Pinia优点

2.1 直观

Stores 和组件一样熟悉。API 旨在让您编写组织良好的stores。

2.2 类型安全

类型是推断出来的,这意味着即使在 JavaScript 中,stores也为您提供自动完成功能

2.3 开发者工具支持

Pinia 与 Vue devtools 挂钩,提供增强的 Vue 2 和 Vue 3 开发体验。

2.4 可扩展

响应存储更改以通过事务、本地存储同步等扩展 Pinia。

2.5 模块化设计

构建多个stores并让打包程序代码自动拆分它们。

2.6 极轻

Pinia 大小约1kb

3.基本使用

// stores/counter.js
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => {
    return { count: 0 }
  },
  // could also be defined as
  // state: () => ({ count: 0 })
  actions: {
    increment() {
      this.count++
    },
  },
})

在组件中使用它:

import { useCounterStore } from '@/stores/counter'

export default {
  setup() {
    const counter = useCounterStore()

    counter.count++
    // with autocompletion ✨
    counter.$patch({ count: counter.count + 1 })
    // or using an action instead
    counter.increment()
  },
}

您甚至可以使用函数(类似于组件setup())为更高级的用例定义 Store:

export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  function increment() {
    count.value++
  }

  return { count, increment }
})

如果不熟悉setup()Composition API,别担心,Pania 也支持类似 Vuex的 map helpers。您以相同的方式定义stores,使用mapStores()mapState(), 或mapActions()

const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  getters: {
    double: (state) => state.count * 2,
  },
  actions: {
    increment() {
      this.count++
    }
  }
})

const useUserStore = defineStore('user', {
  // ...
})

export default {
  computed: {
    // other computed properties
    // ...
    // gives access to this.counterStore and this.userStore
    ...mapStores(useCounterStore, useUserStore)
    // gives read access to this.count and this.double
    ...mapState(useCounterStore, ['count', 'double']),
  },
  methods: {
    // gives access to this.increment()
    ...mapActions(useCounterStore, ['increment']),
  },
}

Pinia官网链接