vue3 第三十九节(pinia的用法注意事项解构store)

pinia 主要包括以下五部分,经常用到的是 store、state、getters、actions

以下使用说明,注意事项,仅限于 vue3 setup 语法糖中使用,若使用选项式 API 请直接查看官方文档:

一、前言:

pinia 是为了探索 vuex 下一次迭代是要实现那些功能用途,pinia 已实现vuex5 的绝大部分功能; 并且与 Vuex 相比,Pinia 提供了一个更简单的 API,具有更少的规范,提供了 Composition-API 风格的 API,最重要的是,在与 TypeScript 一起使用时具有可靠的类型推断支持;

二、pinia 与vuex <= 4.x 的差异

1、****mutations 不再存在。他们经常被认为是 非常 冗长。他们最初带来了 devtools 集成,但这不再是问题。 **2、**无需创建自定义复杂包装器来支持 TypeScript,所有内容都是类型化的,并且 API 的设计方式尽可能利用 TS 类型推断。 **3、**不再需要注入、导入函数、调用函数、享受自动完成功能4、****无需 动态添加 Store,默认情况下它们都是动态的,您甚至都不会注意到。请注意,您仍然可以随时手动使用 Store 进行注册,但因为它是自动的,您无需担心。 **5、**不再有 modules 的嵌套结构 。您仍然可以通过在另一个 Store 中导入和 使用 来隐式嵌套 Store,但 Pinia 通过设计提供平面结构,同时仍然支持 Store 之间的交叉组合方式。 您甚至可以拥有 Store 的循环依赖关系。 **6、**没有 命名空间模块 。鉴于 Store 的扁平架构,"命名空间" Store 是其定义方式所固有的,您可以说所有 Store 都是命名空间的。

三、store:

store :它持有 未绑定到您的组件树的状态和业务逻辑托管全局状态 像一个始终存在并且每个人都可以读取和写入 的组件; 主要有三个方法:state、getters、actions,类似于组件中数据、计算属性、方法; 用于存储不同组件直接共享的数据实例方法,以及页面之间需要保留的数据状态;

xml 复制代码
// count.ts 文件
<script lang="ts">
import { defineStore } from 'pinia'
// defineStore 的第一个参数是 唯一标识ID 用于关联 devtool 调试使用
// 第二个参数是 一个对象 包含 state、actions,gettes
// 声明的 属性useCount  建议以 use 开头,保持书写的统一性
export const useCount = defineStore('count', {
    state:() => {
        return{

        }
    },
    actions: {},
    gettes: {}
})
</script>

在组件中使用: 注意:若 解构使用 store 中的属性 方法,需要使用 storeToRefs() 或者 toRefs() 让其保持响应式

xml 复制代码
<script setup>
    import { toRefs } from 'vue'
    import { storeToRefs } from 'pinia'
    import { useCount } from '@/store'
    const count = useCount()
    // 这样解构获取 store 中属性方法,会丢失响应式
    const { num } = count
    // 1、使用 pinia自带的storeToRefs(), 将store中属性转换为 ref 数据以保持响应式
    const { doubleCountAdd } = storeToRefs(count)
    console.log('=doubleCountAdd==', doubleCountAdd)
    // 2、使用vue3 的 toRefs() 转化为 ref 响应式数据
    const { doubleCount }  = toRefs(count)
    console.log('=doubleCount==', doubleCount)
</script>

四、state:

state: 类似组件中的 data(){return{}},但是在 pinia 中的state 建议书写为: 使用箭头函数,用于完整推断类型

dart 复制代码
state: () => {
    return {
        name: 'Andy',
        num: 0
    }
}

组件中使用:

xml 复制代码
<script setup lang='ts'>
    import { useCount } from '@/store'
    const count = useCount()
    // 1、直接调用或者修改
    console.log(count.name)
    // 2、通过$patch({}) 同时修改多个属性
    count.$patch({
        name: '刺客',
        num++
    })
    // 或者传入一个回调函数
    count.$patch((state) => {
        state.count = '4'
    })
</script>

五、actions: actions 类似组件中的methods,可以在组件中直接调用里面的方法

xml 复制代码
// count.ts 文件
<script lang="ts">
export const useCount = defineStore('count', {
    state: () => {
        return{
            name: 'Andy',
            num: 0
        }
    },
    actions: {
        add() {
            // 直接通过 this 调用 state 中的属性,也可以调用其他 store 中属性,只需引入即可
            this.num++
        },

    },
})
</script>

组件中可以直接通过 调用 add() 方法来修改 num

xml 复制代码
<script setup>
    import { useCount } from '@/store'
    const count = useCount()
    count.add() 
</script>

六、gettes:

相当于组件中的 computed 计算属性:

typescript 复制代码
// count.ts 文件
<script lang='ts'>
import { defineStore } from 'pinia'
export const useCount = defineStore('count', {
    state: () => {
        return{
            name: 'Andy',
            num: 0
        }
    },
    getters: {
        // 相当于组件中的 计算属性
        doubleCount(state): number {
            return  state.num * 2
        },
        doubleCountAdd():number {
            // 可以在其他 getter 中直接调用另一个getter
            return this.doubleCount + 1
        },
        // 接收额外参数时,需要返回一个函数处理
        doubleCountAdd2:(state) => {
            return (num:number):number => state.num * num
        } 
    }
})
</script>

在组件中可以直接使用

xml 复制代码
<script setup>
import { useCount } from '@/store'
const count = useCount()
console.log(count.doubleCountAdd)
count.$patch({
    name: '刺客',
    num: 3
})

const doubleCountAdd2 = count.doubleCountAdd2(8)
 // 上面state.num 值为 3, 传入 额外参数 为8,故最后为  3* 8 = 24
</script>

完整代码如下:

typescript 复制代码
// count.ts 文件
import { defineStore } from 'pinia'
// 通过 defineStore 定义的 store 第一个参数 count 是唯一的id,用于链接devtool
// 定义 一个id 为count的 store 

export const useCount = defineStore('count', {
    state: () => {
        return{
            name: 'Andy',
            num: 0
        }
    },
    actions: {
        add() {
            this.num++
        },

    },
    // getter 只会依赖状态
    getters: {
        // 相当于组件中的 计算属性
        doubleCount(state): number {
            return  state.num * 2
        },
        doubleCountAdd():number {
            // 可以在其他 getter 中直接调用另一个getter
            return this.doubleCount + 1
        },
        // 接收额外参数,返回一个函数处理
        doubleCountAdd2:(state) => {
            return (num:number):number => state.num * num
        } 
    },
    // 若不需要额外配置,
    // persist: true,
    // 额外配置
    persist: {
        // key: 'piniaStore', //存储名称
        // storage: sessionStorage, // 存储方式 默认存储在localStorage
        // paths: ['name'], //指定 state 中哪些数据需要被持久化。[] 表示不持久化任何状态,undefined 或 null 表示持久化整个 state
    }
})
javascript 复制代码
// main.ts 文件
import { createApp } from 'vue'
import { createPinia } from 'pinia'
const app = createApp(App)
const pinia = createPinia()
//导入pinia 持久化 插件
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
pinia.use(piniaPluginPersistedstate)
app.use(pinia)
app.mount('#app')

// 单文件组件 myPinia/index.vue 文件中使用

xml 复制代码
<template>
  <div class="myPinia">
    This is a text demo of the pinia.
    <hr>
    <div>count.num: {{ count.num }}</div>
    <div>count.doubleCount: {{ count.doubleCount }}</div>
    <div>count.doubleCountAdd: {{ count.doubleCountAdd }}</div>
    <div>num: {{ num }}</div>
    <div>doubleCountAdd: {{ doubleCountAdd }}</div>
    <div>doubleCount: {{ doubleCount }}</div>
    <div>doubleCountAdd2: <span>{{ doubleCountAdd2 }}</span></div>

    <button @click="count.add()">add</button>
  </div>
</template>

<script setup>
import { toRefs } from 'vue'
import { storeToRefs } from 'pinia'
import { useCount } from '@/store'
const count = useCount()
console.log('==count==', count)
// 解构获取 store 中属性方法,不是响应式
const { num } = count
// 1、使用 pinia自带的storeToRefs(), 将store中属性转换为 ref 数据以保持响应式
const { doubleCountAdd } = storeToRefs(count)
console.log('=doubleCountAdd==', doubleCountAdd)
// 2、使用vue3 的 toRefs() 转化为 ref 响应式数据
const { doubleCount }  = toRefs(count)
console.log('=doubleCount==', doubleCount)
// 通过 $patch 修改state 中多个属性
count.$patch({
      name: '刺客',
      num: 3
  })
  // 传入额外参数
  const doubleCountAdd2 = count.doubleCountAdd2(8) // 上面state.num 值为 3, 传入 额外参数 为8,故最后为  3* 8 = 24
</script>

<style lang="scss" scoped>

div{
  font-size: 18px;
  color: #333;
  span {
    color: red;
  }
}
</style>
相关推荐
hikktn22 分钟前
【开源宝藏】30天学会CSS - DAY6 第六课 流光文字动画
前端·css·开源
samroom41 分钟前
React-Router路由跳转、传参、抽象封装以及嵌套路由
前端·react.js·前端框架
magic 2451 小时前
移动端WEB开发之响应式布局
前端·css·html·html5
fridayCodeFly1 小时前
:class=“{ ‘addCheckstyle‘: hasError }“这是什么意思
前端·javascript·vue.js
知识分享小能手1 小时前
CSS3学习教程,从入门到精通,CSS3 布局语法知识点及案例代码(15)
前端·css·学习·html·css3·html5·java后端开发
木木黄木木1 小时前
使用CSS3实现炫酷的3D翻转卡片效果
前端·3d·css3
Sperains1 小时前
响应式数组操作在Vue3和React中的差异
前端
阿黄学技术1 小时前
Spring框架核心注解(Spring,SpringMVC,SpringBoot)
前端·spring boot·spring
小璞1 小时前
1. Webpack 核心概念
前端·webpack
lee5761 小时前
用Promise实现ajax的自动重试
前端·javascript·ajax