pinia@2

介绍

​ Pinia (发音为 /piːnjʌ/,类似英文中的 “peenya”) 是最接近有效包名 piña (西班牙语中的 pineapple,即“菠萝”) 的词,是一个状态管理插件,允许跨组件,跨页面共享状态。vuex的升级版,相比于vuex少了一个mutation

下面的内容我将配合vue3的组合式API来演示,推荐使用vue3组合式API,建议通过 pnpm add pinia 来进行安装

基础

配置到项目

​ 在项目中启用pinia

// /src/main.js 文件
import { createPinia } from 'pinia'
app.use(createPinia())

注:在此目录下新建/src/stores/counter.js 文件存放我们的例子,一般来说我们将状态文件放入 stores 目录下

​ 选项式写法

import { defineStore } from 'pinia'

// 参数一定义的是唯一ID,是必须传入的, Pinia 将用它来连接 store 和 devtools
export const useCounterStore = defineStore('counter', {
    state: () => ({ count: 0 }),
    getters: {
    	double: (state) => state.count * 2,
    },
    actions: {
        increment() {
            this.count++
        },
    },
})

​ 函数式写法 (记得最后需要返回参数!)

import { defineStore } from 'pinia'

// 参数一定义的是唯一ID,是必须传入的, Pinia 将用它来连接 store 和 devtools
export const useCounterStore = defineStore('counter', () => {
    const count = ref(0)
    function increment() {
    	count.value++
    }
    return { count, increment }
})

Tips: 导出的函数一般要带有use前缀,一般都是这样命名的


State

​ 定义一个返回初始状态(对象)的函数

import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', () => {
    state: ()=> ({
        count: 0,		// 定义数据
    })
})

​ 应用

import { useCounterStore,storeToRefs } from './stores/counter.js'

const counterStore1 = useCounterStore()		// 每一个useCounterStore都相同
const counterStore2 = useCounterStore()		// 两者相等,这不能直接解构,解构会失去响应式
const counterStore3 = useCounterStore()	
const { count } = storeToRefs(counterStore3)	// 可以通过官方方法解构

console.log(++counterStore1.count)	// 这里将会非常简单



counterStore1.$reset()	// 可以通过调用 store 的 $reset() 方法将 state 重置为初始值。
counterStore1.$patch({	// 同时间给多个属性赋值
  count: counterStore1.count + 1,
  age: 120,
  name: 'DIO',
})
counterStore1.$patch((state) => {	// 上面的函数式写法
  state.items.push({ name: 'shoes', quantity: 1 })
  state.hasChanged = true
})


// 订阅这个Store,每当Store的发生了变化,就调用
cartStore.$subscribe((mutation, state) => {
  // import { MutationType } from 'pinia'
  mutation.type // 'direct' | 'patch object' | 'patch function'
  // 和 cartStore.$id 一样
  mutation.storeId // 'cart'
  // 只有 mutation.type === 'patch object'的情况下才可用
  mutation.payload // 传递给 cartStore.$patch() 的补丁对象。

  // 每当状态发生变化时,将整个 state 持久化到本地存储。
  localStorage.setItem('cart', JSON.stringify(state))
})

Getter

​ 就是store => state 的计算值, 通过 defineStore() 中的 getters 属性来定义它们。推荐使用箭头函数,并且它将接收 state 作为第一个参数

// 非常简单,这里就不多讲了,就是vue的计算属性

export const useStore = defineStore('main', {
  state: () => ({
    count: 0,
  }),
  getters: {
    doubleCount: (state) => state.count * 2,
  },
})

Action

​ 相当于vue中的methods,主要写业务逻辑的


export const useCounterStore = defineStore('main', {
  state: () => ({
    count: 0,
  }),
  actions: {
    increment() {
      this.count++
    },
    randomizeCounter() {
      this.count = Math.round(100 * Math.random())
    },
  },
})

​ 订阅某个store的action,可以通过 store.$onAction() 来监听 action 和它们的结果。传递给它的回调函数会在 action 本身之前执行。after 表示在 promise 解决之后,允许你在 action 解决后执行一个回调函数。同样地,onError 允许你在 action 抛出错误或 reject 时执行一个回调函数。这些函数对于追踪运行时错误非常有用,类似于Vue docs 中的这个提示

const unsubscribe = someStore.$onAction(
  ({
    name, // action 名称
    store, // store 实例,类似 `someStore`
    args, // 传递给 action 的参数数组
    after, // 在 action 返回或解决后的钩子
    onError, // action 抛出或拒绝的钩子
  }) => {
    // 为这个特定的 action 调用提供一个共享变量
    const startTime = Date.now()
    // 这将在执行 "store "的 action 之前触发。
    console.log(`Start "${name}" with params [${args.join(', ')}].`)

    // 这将在 action 成功并完全运行后触发。
    // 它等待着任何返回的 promise
    after((result) => {
      console.log(
        `Finished "${name}" after ${
          Date.now() - startTime
        }ms.\nResult: ${result}.`
      )
    })

    // 如果 action 抛出或返回一个拒绝的 promise,这将触发
    onError((error) => {
      console.warn(
        `Failed "${name}" after ${Date.now() - startTime}ms.\nError: ${error}.`
      )
    })
  }
)

// 手动删除监听器
unsubscribe()
posted @ 2023-05-10 17:50  Pro成  阅读(51)  评论(0编辑  收藏  举报