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>
相关推荐
文心快码BaiduComate4 分钟前
新增Zulu-CLI、企业版对话支持自定义模型、一键设置自动执行、复用相同终端,8月新能力速览!
前端·后端·程序员
walking9577 分钟前
JavaScript 神技巧!从 “堆代码” 到 “写优雅代码”,前端人必看
前端·面试
前端西瓜哥12 分钟前
图形编辑器开发:基于矩阵的画布缩放和移动实现
前端
walking95712 分钟前
前端 er 收藏!高性价比 JS 工具库,轻量又强大
前端·面试
gongzemin21 分钟前
Vue 项目权限管理 路由 按钮权限
前端·vue.js
walking95728 分钟前
效率党必藏! JavaScript 自动化脚本,覆盖文件管理、天气查询、通知提醒(含详细 demo)
前端·面试
lichenyang45329 分钟前
用React写一个技能冷却的案例,关于节流
前端
walking95732 分钟前
前端进阶必看!藏在浏览器与代码里的技巧
前端
Flame_40 分钟前
一行代码搞定Vue3异步请求:vue3-request让状态管理从地狱到天堂
vue.js
又写一个小bug1 小时前
如何让你的Vue项目支持局域网访问 - 完整指南
前端