什么是Pinia? 为什么当你的Vue用上Pinia你就离不开它?

7,457次阅读
没有评论

共计 2556 个字符,预计需要花费 7 分钟才能阅读完成。

为什么你应该使用 Pinia?

什么是 Pinia? 为什么当你的 Vue 用上 Pinia 你就离不开它?

Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。如果你熟悉组合式 API 的话,你可能会认为可以通过一行简单的 export const state = reactive({}) 来共享一个全局状态。对于单页应用来说确实可以,但如果应用在服务器端渲染,这可能会使你的应用暴露出一些安全漏洞。而如果使用 Pinia,即使在小型单页应用中,你也可以获得如下功能:

  • Devtools 支持追踪 actions、mutations 的时间线在组件中展示它们所用到的 Store 让调试更容易的 Time travel
  • 热更新不必重载页面即可修改 Store 开发时可保持当前的 State
  • 插件:可通过插件扩展 Pinia 功能
  • 为 JS 开发者提供适当的 TypeScript 支持以及自动补全功能。
  • 支持服务端渲染

为什么取名 Pinia?

Pinia (发音为 /piːnjʌ/,类似英文中的“peenya”) 是最接近有效包名 piña (西班牙语中的 pineapple,即“菠萝”) 的词。菠萝花实际上是一组各自独立的花朵,它们结合在一起,由此形成一个多重的水果。与 Store 类似,每一个都是独立诞生的,但最终它们都是相互联系的。它 (菠萝) 也是一种原产于南美洲的美味热带水果。

对比 Vuex

Pinia 起源于一次探索 Vuex 下一个迭代的实验,因此结合了 Vuex 5 核心团队讨论中的许多想法。最后,我们意识到 Pinia 已经实现了我们在 Vuex 5 中想要的大部分功能,所以决定将其作为新的推荐方案来代替 Vuex。

与 Vuex 相比,Pinia 不仅提供了一个更简单的 API,也提供了符合组合式 API 风格的 API,最重要的是,搭配 TypeScript 一起使用时有非常可靠的类型推断支持。

RFC

最初,Pinia 没有经过任何 RFC 的流程。我基于自己开发应用的经验,同时通过阅读其他人的代码,为使用 Pinia 的用户工作,以及在 Discord 上回答问题等方式验证了一些想法。这些经历使我产出了这样一个可用的解决方案,并适应了各种场景和应用规模。我会一直在保持其核心 API 不变的情况下发布新版本,同时不断优化本库。

现在 Pinia 已经成为推荐的状态管理解决方案,它和 Vue 生态系统中的其他核心库一样,都要经过 RFC 流程,它的 API 也已经进入稳定状态。

对比 Vuex 3.x/4.x

Vuex 3.x 只适配 Vue 2,而 Vuex 4.x 是适配 Vue 3 的。

Pinia API 与 Vuex(

  • mutation 已被弃用。它们经常被认为是极其冗余的。它们初衷是带来 devtools 的集成方案,但这已不再是一个问题了。
  • 无需要创建自定义的复杂包装器来支持 TypeScript,一切都可标注类型,API 的设计方式是尽可能地利用 TS 类型推理。
  • 无过多的魔法字符串注入,只需要导入函数并调用它们,然后享受自动补全的乐趣就好。
  • 无需要动态添加 Store,它们默认都是动态的,甚至你可能都不会注意到这点。注意,你仍然可以在任何时候手动使用一个 Store 来注册它,但因为它是自动的,所以你不需要担心它。
  • 不再有嵌套结构的模块。你仍然可以通过导入和使用另一个 Store 来隐含地嵌套 stores 空间。虽然 Pinia 从设计上提供的是一个扁平的结构,但仍然能够在 Store 之间进行交叉组合。你甚至可以让 Stores 有循环依赖关系。
  • 不再有可命名的模块。考虑到 Store 的扁平架构,Store 的命名取决于它们的定义方式,你甚至可以说所有 Store 都应该命名。

基础示例

先创建一个 Store:


import {defineStore} from 'pinia'

export const useCounterStore = defineStore('counter', {state: () => {return {count: 0 }
  },
  
  
  actions: {increment() {this.count++
    },
  },
})

然后你就可以在一个组件中使用该 store 了:


为实现更多高级用法,你甚至可以使用一个函数 (与组件 setup() 类似) 来定义一个 Store:

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

  return {count, increment}
})

如果你还不熟悉 setup() 函数和组合式 API,别担心,Pinia 也提供了一组类似 Vuex 的 映射 state 的辅助函数。你可以用和之前一样的方式来定义 Store,然后通过 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 defineComponent({
  computed: {...mapStores(useCounterStore, useUserStore)
    
    ...mapState(useCounterStore, ['count', 'double']),
  },
  methods: {...mapActions(useCounterStore, ['increment']),
  },
})

想学习更系统的学习 Pinia, 请访问《Pinia 中文教程》

原文地址: 什么是 Pinia? 为什么当你的 Vue 用上 Pinia 你就离不开它?

    正文完
     0
    Yojack
    版权声明:本篇文章由 Yojack 于2024-09-20发表,共计2556字。
    转载说明:
    1 本网站名称:优杰开发笔记
    2 本站永久网址:https://yojack.cn
    3 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
    4 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
    5 本站所有内容均可转载及分享, 但请注明出处
    6 我们始终尊重原创作者的版权,所有文章在发布时,均尽可能注明出处与作者。
    7 站长邮箱:laylwenl@gmail.com
    评论(没有评论)