前端学习笔记 6:Pinia

2024-01-09 16:03:38

前端学习笔记 6:Pinia

Pinia 是 Vue 的一个官方库,用于状态管理。

1.安装

首先创建一个 Vue3 项目,具体方式可以参考这里

安装 Pinia:

npm install pinia

创建一个 pinia 实例 (根 store) 并将其传递给应用:

import './assets/main.css'

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const pinia = createPinia()
const app = createApp(App)
app.use(pinia)
app.mount('#app')

2.定义 Store

import { defineStore } from "pinia"
export const useCounterStore = defineStore('counter', {
    state: () => ({ count: 0 }),
    getters: {
        double: (state) => state.count * 2,
    },
    actions: {
        increment() {
            this.count++
        },
    },
})

通过函数defineStore定义 Store,返回值useCounterStore同样是一个函数,且通常以useXXXStore的方式命名。第一个参数是 Store 的名称,第二个参数是对象,其中包含三部分:

  • state:Store 的状态(数据)
  • getters:计算属性(类似于computed的返回值)
  • actions:Store 的方法

通常,会使用更简洁的组合式 API 进行定义:

import { defineStore } from "pinia";
import { computed,ref } from "vue";
export const useCountStore = defineStore('count', () => {
    // 定义 state
    const count = ref(0)
    // 定义 getter
    const doubleCount = computed(() => { return count.value * 2 })
    // 定义 action
    const increment = () => {
        count.value++
    }
    return {count, doubleCount, increment}
})

3.使用 Store

<script setup>
import {useCountStore} from '@/stores/count'
const countStore = useCountStore()
</script>
<template>
    <button @click="countStore.increment">{{ countStore.count }}</button>
    <div>{{ countStore.doubleCount }}</div>
</template>

4.异步 Action

Store 的 Action 中不仅可以定义同步方法,也可以定义异步方法:

import axios from "axios";
import { defineStore } from "pinia";
import { ref } from "vue";

const API_URL = 'http://geek.itheima.net/v1_0/channels'
export const useListStore = defineStore('list', ()=>{
    const list = ref([])
    const getList = async ()=>{
        const result = await axios.get(API_URL)
        list.value = result.data.data.channels
    }
    return {list, getList}
})

使用异步方法的方式与同步方法相同:

<script setup>
import {useListStore} from '@/stores/list'
const listStore = useListStore()
listStore.getList()
</script>
<template>
    <li v-for="channel in listStore.list" :id="channel.id">{{ channel.name }}</li>
</template>

5.解析 Store

像上面展示的那样,通常都需要在使用 Store 时使用.操作符引用其属性或方法,你可能期望使用解析操作符对 Store 对象解析,以更方便地使用:

<script setup>
import {useCountStore} from '@/stores/count'
const countStore = useCountStore()
const {count, doubleCount, increment} = countStore
</script>
<template>
    <button @click="increment">{{ count }}</button>
    <div>{{ doubleCount }}</div>
</template>

实际上这段示例是有 bug 的,因为这里的countStore解析后,获取的属性countdoubleCount都是普通数值,而不是响应式数据(Ref 对象),所以并不会随着点击按钮而发生变化。

要想从 Store 中解析出响应式数据,要使用storeToRefs函数包裹 Store 实例:

<script setup>
import { useCountStore } from '@/stores/count'
import { storeToRefs } from 'pinia'
const countStore = useCountStore()
const { increment } = countStore
const { count, doubleCount } = storeToRefs(countStore)
</script>
<template>
    <button @click="increment">{{ count }}</button>
    <div>{{ doubleCount }}</div>
</template>

需要注意的是,storeToRefs方法返回的对象中是不包含 Store 的 Action 的,所以要以解析的方式获取方法依然要解析原始的 Store 实例。

6.debug

对 Store 相关的数据 debug 可以使用 Vue 的 debug 插件 Vue.js devtools - Microsoft Edge Addons

image-20240109141320265

7.参考资料

文章来源:https://blog.csdn.net/hy6533/article/details/135479357
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。