Pinia基础使用(Vue3)

182 阅读1分钟

Pinia中文官网

准备工作:初始化一个Vue的项目

1.安装pinia

npm i --save pinia

2.引入并注册

//  src/main.js

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

3.创建store

//  src/store/user.js

import { defineStore } from 'pinia'

export const useUserStore = defineStore('main',{})
//第一个参数是该store的唯一id(string)
//第二个参数是该store的配置项,配置store内的数据,修改数据的方法等等

4.使用store

在App.js使用store

//  src/App.js

<script>
// 引入store: main
import { useUserStore } from './store/user'
export default {
  name: 'App',
  setup() {
    const store = useUserStore()
    console.log(store)
    return {
      store
    }
  }
}
</script>

5.在store中添加state

//  src/store/user.js

import { defineStore } from 'pinia'

export const useUserStore = defineStore('main',{
    state: () => {
      return {
        name:'孙悟空',
        age: 18
      }
    }
})
//配置项中的state属性是一个函数,不能直接写成对象

6.操作state

1.读取state

<script>
import { useUserStore } from './store/user'
export default {
  name: 'App',
  setup() {
    const store = useUserStore()
    //console.log(store.name)
    const {name} = store 
    //注意,直接解构的话不具有响应式
    return {
      store,
      name
    }
  }
}
</script>

2.修改state

//使数据具有响应式
const { name } = storeToRefs(store)

// 1)直接修改
store.name = 'xxx'

// 2)批量修改
store.$patch = {
counter: store.counter + 1,
  name: 'Abalam',
}
//但是,使用这种语法应用某些突变非常困难或代价高昂:任何集合修改(例如,从数组中推送、
//删除、拼接元素)都需要您创建一个新集合。 正因为如此,`$patch` 方法也接受一个函数来
//批量修改集合内部分对象的情况:
store.$patch((state) => {
  state.items.push({ name: 'shoes', quantity: 1 })
  state.hasChanged = true
})

// 3)替换state
store.$state = { counter: 666, name: 'Paimon' }
//或
pinia.state.value = {}

// 4)订阅状态
store.$subscribe((mutation, state) => {
  // import { MutationType } from 'pinia'
  mutation.type // 'direct' | 'patch object' | 'patch function'
  // 与 store.$id 相同
  mutation.storeId // 'cart'
  // 仅适用于 mutation.type === 'patch object'
  mutation.payload // 补丁对象传递给 to cartStore.$patch()

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

7.getters

Getter 完全等同于 Store 状态的 计算值(类似vue2的computed),在defineStore()的配置项中 1)基本使用

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

2)访问其他getter

export const useStore = defineStore('main', {
  state: () => ({
    counter: 0,
  }),
  getters: {
    // 类型是自动推断的,因为我们没有使用 `this`
    doubleCount: (state) => state.counter * 2,  //这里不能使用this
   
    doubleCountPlusOne() {
      // 自动完成 ✨
      return this.doubleCount + 1
    },
  },
})

3).给getter传递参数

export const useStore = defineStore('main', {
  getters: {
    getUserById: (state) => {
      return (userId) => state.users.find((user) => user.id === userId)
    },
  },
})

//在组件中使用
<script>
export default {
  setup() {
    const store = useStore()

    return { getUserById: store.getUserById }
  },
}
</script>

<template>
  <p>User 2: {{ getUserById(2) }}</p>
</template>

4)访问其他store的getter

import { useOtherStore } from './other-store'

export const useStore = defineStore('main', {
  state: () => ({
    // ...
  }),
  getters: {
    otherGetter(state) {
      const otherStore = useOtherStore()
      return state.localData + otherStore.data
    },
  },
})

8.action

1)基本使用

import { defineStore } from 'pinia',

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

2)订阅action 使用 store.$onAction() 订阅 action 及其结果,其参数是一个回调函数,该回调函数会在action执行之前执行。

const unsubscribe = someStore.$onAction(
  ({
    name, // action 的名字
    store, // store 实例
    args, // 调用这个 action 的参数
    after, // 在这个 action 执行完毕之后,执行这个函数
    onError, // 在这个 action 抛出异常的时候,执行这个函数
  }) => {
    // 记录开始的时间变量
    const startTime = Date.now()
    // 这将在 `store` 上的操作执行之前触发
    console.log(`Start "${name}" with params [${args.join(', ')}].`)

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

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

// 手动移除订阅
unsubscribe()


//当订阅action时会首先执行回调函数,然后执行action。
//`after` 是处理 Promise 的,允许在 action 完成后执行after函数
//`onError` 允许在处理中抛出错误。