细说Pinia


本篇文章细说一下Vue全家桶中的Pinia,Pinia是官方指定的下一代Vuex,值得一探究竟。

Pinia的优势

Vuex 相比,Pinia有许多优势:

  1. 取消了Mutations

    • 它本身就显得很多余
  2. TypeScript 支持更好,Vuex 对于 TS 的支持很不好
  3. 取消了 modules 的结构嵌套和命名空间的概念

    • 可以灵活的使用每一个 store,它们通过扁平化的方式相互使用。

Pinia的安装和基本使用方法

  1. 安装Pinia的命令:npm install pinia
  2. 在项目新建入口文件,具体路径为src/stores/index.js

    import { createPinia } from 'pinia'
    
    const pinia = createPinia()
    
    export default pinia
  3. main.js 文件中挂载 Pinia

    import pinia from './stores'
    
    // 使用 use() 方法挂载
    createApp().use(pinia)
  4. 定义 store 用于共享状态

    stores 文件夹中新建一个文件用于共享状态,具体路径为src/stores/aaa.js

    import { defineStore } from 'pinia'
    
    // defineStore() 方法第一个参数是 Store 的名字
    // 第二个参数是一个对象,定义共享状态
    // defineStore() 返回的是一个函数
    const useCounter = defineStore('counter', {
        state: () => ({
          count: 11  
        })
    })
    
    // 导出
    export default useCounter
  5. 使用 storecomposition API 的写法)

    在任意的组件中使用。

    <script setup>
        // 导入Store
        import useCounter from '/src/stores/conuter.js'
        
        // 使用 store
        const counterStore = useCounter()
    </script>
    <template>
    <!-- 使用Store里面的值 --!>
    <h2>{{ counterStore.count }}</h2>  <!-- 11 --!>
    </template>

Pinia中Store的解构

如果直接解构Store里面的参数,里面的参数就不是响应式的了,可以使用toRefs()方法进行解构,Pinia也提供了一个方法storeToRefs进行响应式的解构。

import { toRefs } from 'vue'
import { storeToRefs } from 'pinia'

const { count } = toRefs(counterStore)
const { count } = storeToRefs(counterStore)

Pinia中的State

State可以定义初始状态

  1. 修改State

    Vuex中需要使用mutations修改state的值,在pinia中取消了这一概念,允许直接修改值。

    import useCounter from 'xxx'
    const counterStore = useCounter()
    
    // 修改count的值  可以直接修改的
    counterStore.count = 22
  2. 重置State

    $reset()方法可以重置state为初始值。

    const counterStore = useCounter()
    counter.$reset() // 重置为初始状态 11
  3. 一次性修改多个State

    使用$patch()方法可以一次性修改多个值。

    const counterStore = useCounter()
    
    counterStore.$patch({
        count: 33,
        price: 100
    })
  4. 替换State

    使用$state属性可以设置新的对象来替换 store 中整个 state

    const counterStore = useCounter()
    counterStore.$state = {
        count: 44,
        price: 200
    }

Pinia中的Getters

Getters的功能类似于Computed计算属性。基本使用如下:

const useCount = defineStore('count', {
     state: () => ({
            count: 11
        })
    
    getters: {
        // 默认传递一个 state 参数 用于操作state
        increment(state) {
            return state.count * 2
        }
    }
})

export default useCount

使用 Getters

<script setup>
import useCount from 'count.js'

const countStore = useCount()
</script>

<template>
{{ countStore.increment }}    
</template>

一个getter使用另一个getter,在getter中是由this的,this指向的是当前store的实例

const useCount = defineStore('count', {
    state: () => ({
            count: 11
        })
    
    getters: {
        // 默认传递一个 state 参数 用于操作state
        increment(state) {
            return state.count * 2
        },
        incrementAddOne() {
            // this 是 store 实例
            return this.increment +1
        }
    }
})

export default useCount

getter也支持返回一个函数。

getters: {
    findSomeOne(state) {
        return function(id) {
            // 查找 id 相同的一项
            state.Some.find(x => x.id === id)
        }
    }
}

getter使用其他 store 中的数据

// 在 count.js 中

// 导入别的 store
import useUser from 'user.js'

getters: {
    getUserInfo () {
        // 获取 userStore 的信息
        const userStore = useUser()
        // 返回 userStore 的用户信息
        return `name: ${userStore.name}`
    }
}

Pinia中的Actions

Actions适合定义业务逻辑,例如网络请求。action中访问state数据可以使用 this 访问。

defineStore('count', {
    state: () => ({
        count: 10
    })
    actions: {
        increment(num) {
            // num 是接收传递过来的参数的
            // 使用this访问store实例
                return this.count++
    
            return this.count += num
        }
    }
})

使用Actions

<script setup>
    import useCount from 'count.js'
    function addClick() {
        // 调用 actions 中的方法
        useCount.increment()
        // 调用时可以传递参数
        useCount.increment(10)
    }
</script>

Actions可以发起异步请求

actions: {
    async getInfo() {
        const res = await fetch('https://xxx')
        // 将数据存到state的info中
        this.info = res.data.info
    }
}

声明:极客角度|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - 细说Pinia


拒绝拖延,勇于表达!