【vue3 Pinia使用与讲解】vue3新一代的Store应用工具

46 篇文章 6 订阅
30 篇文章 0 订阅

本文章旨在快速帮助上手Pinia基础与核心部分,想要完整了解的请看官网或后续文章,Pinia 还可用于SSR。还有:这中文名可以叫菠萝,起源是西班牙语piña,中文译为菠萝。

Pinia概要:

Pinia一开始是为了探索Vuex的下一次迭代会是什么样子,它融合了Vuex 5核心团队讨论中的许多想法。
最终,我们意识到Pinia已经实现了Vuex 5中我们想要的大部分功能,并决定将 Pinia 作为新的推荐。

与 Vuex 相比,Pinia 提供了一个更简单的 API,没那么死板,提供了 Composition-API 风格的 API,
在与 TypeScript 一起使用时具有更好的类型推断支持。


什么是 Pinia Store ?

Store(比如Pinia)是一个独立存在的,它保存状态和业务逻辑,而不绑定到组件树。
换句话说,它是全局状态的主人。
它有点像一个组件,一直存在着,每个人都可以读写。
它包含三个概念,state、getters 和 actions,可以理解为这些概念相当于组件中的data、computed 和 methods。


什么时候应该使用 Store ?

存储应该包含可以在整个应用程序中访问的数据。
这包括在许多地方使用的数据,例如在导航栏中显示的用户信息,以及需要通过页面保存的数据,例如非常复杂的多步骤表单。
另一方面,您应该避免在 Store 中存储一个组件里的内部数据,例如组件模板内元素的可见性。
并非所有应用程序都需要访问全局状态,但如果您需要一个,Pinia会让你的开发更轻松。


Pinia 的主要 Api

  * createPinia
    - Plugins
  * defineStore  >>  声明一个Store
  * storeToRefs  >>  见`4.`使用案例
  * mapState  >> 在vue组件的options的computed中使用
  * mapGetters  >> mapState的别名,改用mapState
  * mapActions  >> 在vue组件的options的methods中使用
  * getActivePinia  >> 获取当前活动的 pinia 实例(如果有)。
- Store的核心配置:
  + State
  + Getters
  + Actions


vite + vue3 使用方式:

1. npm install pinia

    (当前文章使用的最新版本:2.0.11,若pinia版本变动导致写法不一致,本文章会持续更新)

2. 创建一个 pinia(根存储)并将其传递给vue应用实例:

import { createApp,h } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'
const app = createApp(App)
app.use(createPinia())

3. 定义 Store

在深入研究核心概念之前,我们需要知道 Pinia 是使用 defineStore() 定义的,并且它需要一个唯一的 name 作为第一个参数传递:
name(也称为id)是必需的,Pinia使用 name 参数将 Store 连接到 devtools。
将返回的函数命名为 `use…` 是一种跨组件的约定,使其用法规范化。

  • defineStore(name,options)
    • name: 必传,类型`string`
    • options:{}
import { defineStore } from 'pinia'
// useStore可以是任何类似useUser、useCart的东西
// 第一个参数是应用程序中 Store 的唯一id
export const useStore = defineStore('main', {
  // state: () => ({ count: 0 }),
  state:()=>{
    return {
      // 所有这些属性都将自动推断其数据类型
      items: [],
      counter: 0,
      name: 'Eduardo',
      isAdmin: true,
    }
  },
  getters: {
    doubleCount: (state) => state.counter * 2,
    //doubleCount(state){
    //  console.log(this,'想要在getter中获取该store的其他内容则不能用箭头函数,')
    //  return state.counter * 2
    //},
  },
  actions: {
    increment(num,test1,test2) {
      console.log(num,test1,test2)
      this.counter++
    },
    randomizeCounter() {
      this.counter = Math.round(100 * Math.random())
    },
  }
})



4. 使用 Store

我们之所以声明store,是因为在`setup()`内部调用`useStore()`之前不会创建存储:

还有,不要看到不是<script setup>就吐槽这吐槽那,例子用什么都行,不要连抄都不会抄 [笑哭]

<template>
  <p>Double count is {{ store.doubleCount }}</p>
</template>
<script>
import { mapState } from 'pinia'
import { useStore} from '@/stores/counter'
export default {
  setup() {
    const store = useStore()
    store.counter++
    store.$patch({ // 除了直接用store.counter++改变store之外,您还可以调用该$patch方法。state它允许您对部分对象同时应用多个更改:
      counter: store.counter + 1,
      name: 'Abalam',
    })

    store.$patch((state) => { // $patch 方法还接受一个函数,用于应对复杂数据的修改过程
      state.items.push({ name: 'shoes', quantity: 1 })
      state.isAdmin = false
    })

    store.increment(9,'测试多参数1','测试2') // 调用 actions 并传入参数
    store.randomizeCounter() // 调用 actions
    return {
      // 您可以返回整个store实例以在模板中使用它
      store,
    }
  },
  computed: { 
    storeCounter() {
      return this.store.counter * 3
    },
    // ...mapState(useCounterStore, ['counter']) // 没有 setup 的时候才使用这方式
  },
}
</script>


定义多个 Store

这种基本完爆vuex的modules,任何不相关的模块直接单独定义一个新store。任意组件、任意store想要使用任意一个或多个store都没问题。

您可以根据需要定义任意数量的Store,并且应该在不同的文件中定义每个Store以充分利用 pinia(例如自动允许您的包进行代码拆分和 TypeScript 推理)。

一旦 Store 被实例化,您就可以直接访问存储上的state、getter和actions中定义的任何属性。

// otherStore.ts

import { defineStore } from 'pinia'
export const useOtherStore = defineStore('otherStore', {
  state: () => ({
    count: 2
  }),
  getters: {
    doubleCount: (state) => state.count * 2,
  },
})

在其他store中使用otherStore ↓↓↓  >>>  useOtherStore()

// index.ts

import { defineStore } from 'pinia'
import { useOtherStore } from './otherStore'
export const useStore = defineStore('main', {
  state:()=>{
    return {
      // 所有这些属性都将自动推断其数据类型
      items: [],
      counter: 2,
      name: 'Eduardo',
      isAdmin: true,
    }
  },
  getters: {
    doubleCount(state) {
      return this.counter * 2
    },
  },
  actions: {
    increment(num,test1,test2?:string) {
      console.log(useOtherStore());
      console.log(num,test1,test2)
      this.counter++
    },
    randomizeCounter() {
      this.counter = Math.round(100 * Math.random())
    },
  }
})


 注意事项!

// 注意,store 是一个用 reactive 包装的对象,意味着不需要在 getters 后面写 .value ;
// 所以就像 props 在 setup 中一样,不能对其进行 对象解构 操作!
export default defineComponent({
  setup(props) {
    const store = useStore()
    // ❌ 这不起作用,因为它会破坏响应式  >>  This won't work because it breaks reactivity
    // 这跟从`props`解构的原理相同  >>  it's the same as destructuring from `props`
    const { name, doubleCount } = store
    console.log(name) // "eduardo"
    console.log(doubleCount) // 2
    return {
      // 永远都是"eduardo"  >> will always be "eduardo"
      name,
      // will always be 2
      doubleCount,
      // 这种就是正常的响应式数据 >> this one will be reactive
      doubleValue: computed(() => store.doubleCount),
      }
  },
})


为了从 Store 中提取属性同时保持其数据的响应性,您需要使用storeToRefs(). 它将为任何响应性属性创建 refs。
当您仅使用商店中的state但不调用任何action时,这很有用:

import { storeToRefs } from 'pinia'
export default defineComponent({
  setup() {
    const store = useStore()
    // `name` 和 `doubleCount` 是响应式 refs 数据
    // 这还将为插件添加的属性创建引用
    // 但会跳过任何 action 和 不是reactive(非ref/reactive)的属性
    const { name, doubleCount } = storeToRefs(store)

    return {
      name,
      doubleCount
    }
  },
})

QQ交流群:522976012  ,欢迎来玩。

聚焦vue3,但不限于vue,任何前端问题,究其本质,值得讨论,研究与学习。

Vue3 Pinia是一个基于Vue3的状态管理库,它提供了类似于Vuex的全局状态管理能力,同时使用起来更加简单方便。下面是Vue3 Pinia的使用步骤: 1. 安装Vue3 Pinia 你可以使用npm或者yarn安装Vue3 Pinia: ``` npm install pinia ``` 或者 ``` yarn add pinia ``` 2. 创建Pinia Store 你需要创建一个store来管理你的状态。一个store就是一个拥有状态和操作状态的对象。下面是一个例子: ``` import { defineStore } from 'pinia' export const useCounterStore = defineStore({ id: 'counter', state: () => ({ count: 0 }), actions: { increment() { this.count++ } } }) ``` 这个例子中,我们创建了一个名为useCounterStorestore,它拥有一个状态count,初始值为0,并且有一个操作increment,用来增加count的值。 3. 在Vue组件中使用Store 你可以在Vue组件中使用createPinia函数创建一个Pinia实例,并通过inject注入到组件中。然后就可以通过store来获取状态和操作状态了。下面是一个例子: ``` <template> <div> <p>{{ count }}</p> <button @click="increment">+1</button> </div> </template> <script> import { defineComponent, inject } from 'vue' import { useCounterStore } from './store' export default defineComponent({ setup() { const store = useCounterStore() const count = computed(() => store.count) const increment = () => { store.increment() } return { count, increment } } }) </script> ``` 这个例子中,我们通过useCounterStore函数来获取useCounterStore实例,并且通过computed函数来获取count的值。然后我们在increment函数中调用store的increment方法。 4. 相关问题: 1. Vue3 Pinia与Vuex有什么区别? 2. 如何在多个组件之间共享状态? 3. Vue3 Pinia如何处理异步操作? 4. Vue3 Pinia如何处理模块化?
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值