介绍——为什么要使用 Pinia?

Pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态。 如果您熟悉 Composition API,您可能会认为您已经可以通过一个简单的 export const state = reactive({})来共享全局状态。但是这样在SPA页面中还行,在SSR应用中则会使您的应用程序暴露于安全漏洞

Pinia 和 Vuex对比

Vuex: State、Gettes、Mutations(同步)、Actions(异步)

Pinia: State、Gettes、Actions(同步异步都支持)

Pinia 核心特性:

  • dev-tools 支持

    • 跟踪动作、突变的时间线
    • Store 出现在使用它们的组件中
    • time travel 和 更容易的调试
  • 热模块更换
    • 在不重新加载页面的情况下修改您的 Store
    • 在开发时保持任何现有状态
  • 支持options api 和 composition api
  • Actions 支持同步和异步
  • 去除 mutations 比vuex更加精简
  • 为 JS 用户提供更好的 TypeScript 支持
  • 无需手动添加 store,它的模块默认情况下创建就自动注册的
  • 服务器端渲染支持
  • 轻量 压缩后的体积只有1kb左右

Tips: 从 2022-02-07 在 Vue 3 被设置为默认版本开始, Pinia 已正式被官方推荐作为全局状态管理的工具。

Pinia安装

yarn add pinia
# or with npm
npm install pinia

查看你的 package.json ,看看里面的 dependencies 是否成功加入了 Pinia 和它的版本号(下方是示例代码,以实际安装的最新版本号为准):

{"dependencies": {"pinia": "^2.0.11",},
}

Pinia使用

以 Vue3 + TypeScript 为例

引入Pinia

打开 src/main.ts 文件,添加下面那两行有注释的新代码:

import { createApp } from 'vue'
import { createPinia } from 'pinia' // 导入 Pinia
import App from '@/App.vue'createApp(App).use(createPinia()) // 启用 Pinia.mount('#app')

在上面的片段中,你将Pinia添加到Vue项目中,这样你就可以在你的代码中使用Pinia的全局对象。

定义Store

在 store 目录下创建一个 users.ts 为例,我们先定义并导出一个名为 users的模块

// /src/store/user.ts
// 想要使用必须先引入 defineStore;
import { defineStore } from 'pinia';
// 这里我们使用的是es6 的模块化规范进行导出的。// defineStore 方法有两个参数,第一个参数是模块化名字
// 第二个参数是选项,对象里面有三个属性,相比于vuex 少了一个 mutations.
export const useStore = defineStore('users', {state(){  // 存放的就是模块的变量return {count: 1,arr: []}},getters:{ // 相当于vue里面的计算属性,可以缓存数据},actions:{ // 可以通过actions 方法,改变 state 里面的值。}
})

我们需要知道 Store 是使用 defineStore() 定义的,并且它需要一个唯一名称,作为第一个参数传递。defineStore函数接收两个参数name、options:

  • name:一个字符串,必传项,该store的唯一id。
  • options
  1. 其中 state 用来存储全局状态,它必须是箭头函数,为了在服务端渲染的时候避免交叉请求导致的数据状态污染所以只能是函数,而必须用箭头函数则为了更好的 TS 类型推导;
  2. getters 就是用来封装计算属性,它有缓存的功能;
  3. actions 就是用来封装业务逻辑,修改 state。

使用Store

访问state

前面我们创建了一个store,假如我们要在App.vue里面使用它,该如何使用呢?我们在页面中如何访问 state 里的属性 count?

/src/App.vue
<template><div>{{ user_store.count }}</div>
</template>
<script setup lang="ts">
import { useStore } from "../src/store/user";
const user_store= useStore();
console.log(user_store);
console.log(user_store.count);
// 解构
// const { count } = userStore() // 这个是错误的,拿到的数据不是响应式
</script>

上述代码就可以轻松拿到store内的属性值count。

但是,请注意store 是一个用reactive 包裹的对象,就像setup 中的props 一样,我们不能对其进行解构。这样拿到的数据不是响应式的。

为了从 Store 中提取属性同时保持其响应式,您需要使用storeToRefs()。 它将为任何响应式属性创建 refs。 当您仅使用 store 中的状态但不调用任何操作时,这很有用:

<template><div>{{ count }}</div>
</template>
<script lang="ts" setup>
import { storeToRefs } from 'pinia'
import { userStore } from '../src/store/user'
const { count } = storeToRefs(userStore)
</script>

修改state,重置state

/src/App.vue
<template><div>{{ user_store.count }}</div>
</template>
<script setup lang="ts">
import { useStore } from "../src/store/user";
const user_store= useStore();
// 通过 store 实例访问状态来直接修改状态
user_store.count++
// 重置 store 上的 $reset() 方法将状态 重置 到其初始值:
user_store.$reset()
</script>

修改状态

  1. 可以通过 store 实例访问状态来直接读取和写入状态;
  2. 可以通过 $patch方法传递一个函数来修改;
  3. 可以通过 $patch方法传递一个对象来修改;
  4. 当逻辑比较多或者请求的时候,我们就可以封装到示例中 src/store/user.ts 里的 actions 里。(后面讲action会细讲)

重置状态:可以通过调用 store 上的 $reset() 方法将状态 重置 到其初始值。

getters

添加getters

有缓存功能。如下在页面中多次使用,第一次会调用 getters,数据没有改变的情况下之后会读取缓存。

// /src/store/user.ts
import { defineStore } from 'pinia';
export const useStore = defineStore('users', {state(){  // 存放的就是模块的变量return {name: "回忆哆啦没有A梦",age: 25,sex: "男",}},getters: {// 方法一,接收一个可选参数 stategetAddAge(state){console.log('调用了') // 页面中使用了多次,这里只会执行一次,然后缓存起来了return state.age+ 1},// 方法二,不传参数,使用 this// 但是必须指定函数返回值的类型,否则类型推导不出来getAddAge(): number{return this.age+ 1}},actions: {},
})

使用getters

我们在App.vue中想要调用getters内的方法:

// /src/App.vue
<template><p>新年龄:{{ user_store.getAddAge }}</p>
</template>
<script setup lang="ts">
import { useStore } from "../src/store/user";
const user_store= useStore();
</script>

actions

添加actions

添加一个actions方法,修改state。

// /src/store/user.ts
import { defineStore } from 'pinia';
export const useStore = defineStore('users', {state(){  // 存放的就是模块的变量return {name: "回忆哆啦没有A梦",age: 25,sex: "男",}},getters: {},actions: {saveName(name: string) {this.name = name;},},
})

上段代码中我们定义了一个非常简单的actions方法changeState,在实际场景中,该方法可以是任何逻辑,比如发送请求、存储token等等。大家把actions方法当作一个普通的方法即可,特殊之处在于该方法内部的this指向的是当前store。

使用actions

我们在App.vue中想要调用actions内的方法:

// /src/App.vue
<template><div>{{ user_store.count }}</div>
</template>
<script setup lang="ts">
import { useStore } from "../src/store/user";
const user_store= useStore();
const saveName = () => {user_store.saveName("我是哆啦A梦,希望有个一键三连!");
};
</script>

如果还有兴趣学习pinia的其它特点,比如插件、订阅等等,可以移步官网:pinia官网。

vue3使用Pinia进行全局状态管理,Pinia安装和使用,Pinia 和 Vuex的对比相关推荐

  1. 状态管理 - 全局状态管理工具

    文章目录 一.单向数据流 1. 理念示意图 2. 简述 二.什么是全局状态管理模式 三.重点概念 3.1. 什么是全局状态管理模式? 3.2.全局状态管理工具? 3.3. 什么是 vuex 四.在项目 ...

  2. Pinia全新一代状态管理工具Pinia-Vue3全家桶

    自2022年2月7日前端Vue3成为默认版后,Vuex的状态管理地位受收到了Pinia 的挑战.我相信当你使用过Pinia之后,就会果断的抛弃Vuex的.因为Pinia确实太方便和简单了. 学习目标 ...

  3. Pinia下一代vue状态管理工具

    建议大家结合上一篇文章学习:vite+vue script setup语法糖写法:style'me的个人博客  1.pinia是什么? Pinia是一个围绕Vue 3 Composition API的 ...

  4. react全局状态管理_rxv: 在React中用Vue3的reactivity包实现状态管理。

    前言 React的状态管理是一个缤纷繁杂的大世界,光我知道的就不下数十种,其中有最出名immutable阵营的redux,有mutable阵营的mobx,react-easy-state,在hooks ...

  5. 小程序全局状态管理,在页面中获取globalData和使用globalSetData

    GitHub: https://github.com/WozHuang/mp-extend 主要目标 微信小程序官方没有提供类似vuex.redux全局状态管理的解决方案,但是在一个完整的项目中各组件 ...

  6. react获取全局_使用react hooks实现的简单全局状态管理

    注意,此代码存储库已被弃用,不会再更新维护了. Note that this code repository has been deprecated and will not be updated a ...

  7. 微信小程序----全局状态管理 (便于全局埋点等操作)

    说明 由于我是一个有着一颗玻璃心的博主,导致在2018年后博客很少更新.原因是由于我的分享并没有解决到部分人的问题,而导致被骂了.当时这颗玻璃心就碎了,所以这两年以来很是消极,博客很少更新.这里给那些 ...

  8. 微信小程序:全局状态管理mobx-miniprogram、mobx-miniprogram-bindings

    安装 npm install --save mobx-miniprogram mobx-miniprogram-bindings 定义 store.js /*** 全局状态管理*/ import { ...

  9. 微信小程序API的Promise化及全局状态管理MobX

    文章目录 API的Promise化 创建promise化的对象 全局状态管理 创建 页面中绑定 页面中使用 组件中绑定 组件中使用 API的Promise化 默认情况下小程序官方提供的API都是基于回 ...

最新文章

  1. 教程:11、文件系统
  2. 《Cacti实战》——3.1 检索流程
  3. python代码编辑器下载_编程猫Python编辑器
  4. 7个套路让妹子心甘情愿陪你看魔兽世界大电影
  5. eclipse error pages打红X的解决方法
  6. ubuntu安装 zookeeper3.3.6 由于jdk问题启动失败
  7. 根深才能叶茂:基础软件突破亟待产业界携手创新完善生态
  8. MySql中执行 GROUP BY 分组 遇到 1055错误
  9. mysql的sererdata_MySQL_win2008 R2服务器下修改MySQL 5.5数据库data目录的方法,说明: 操作系统:Windows Server - phpStudy...
  10. 九存:重新定义存储矿机
  11. 波普尔心智格列高利心智_心智与人工智能理论
  12. 【SAP-FICO详细教程】
  13. 虚拟机桥接模式设置IP
  14. python制作动态时钟_python实现简易动态时钟
  15. 康得新董事长是谁?_您人生董事会中的谁?
  16. 月盈利百万的茶馆是如何通过一套商业模式起家?方案分享!
  17. 好用的高匿代理IP有什么特点?
  18. TypeError: __init__() takes exactly 2 arguments (3 given)
  19. J0007. 华为手机怎么开启开发者选项
  20. 关于熔断器Hystrix替代方案的调研报告

热门文章

  1. Dump分析学习指令整理
  2. 音乐相册android studio,音乐相册
  3. 成功解决[Error] reference to ‘xx’ is ambiguous
  4. 人脸识别之SphereFace
  5. nmn听力改善,NMN改善听力的研究,颠覆你的认知
  6. 【java】函数式接口和Stream
  7. PAT 1069. 微博转发抽奖(20)
  8. 服务器压力测试_性能测试新手误区(四):一切来自录制
  9. EAS BOS 报表开发
  10. element-plus 疯狂报警告 ElementPlusError: [Util] binding value must be a string or number.