vue3 快速入门系列 —— 状态管理 pinia

这篇具有很好参考价值的文章主要介绍了vue3 快速入门系列 —— 状态管理 pinia。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

其他章节请看:

vue3 快速入门 系列文章来源地址https://www.toymoban.com/news/detail-859117.html

pinia

vue3 状态管理这里选择 pinia。

虽然 vuex4 已支持 Vue 3 的 Composition API,但是 vue3 官网推荐新的应用使用 pinia —— vue3 pinia

集中式状态管理

redux、mobx、vuex、pinia都是集中式状态管理工具。与之对应的就是分布式。

Pinia 符合直觉的 Vue.js 状态管理库 甚至让你忘记正在使用的是一个状态库 —— 官网

安装 pinia 环境

首先下载安装包:

PS hello_vue3> npm i pinia

added 2 packages, and audited 71 packages in 11s

10 packages are looking for funding
  run `npm fund` for details

1 moderate severity vulnerability

To address all issues, run:      
  npm audit fix

Run `npm audit` for details.  
 "dependencies": {
    "pinia": "^2.1.7",
    "vue": "^3.4.15",
    "vue-router": "^4.3.0"
  },

在 main.ts 中依次:引入、创建和安装 pinia,在浏览器 vue 开发者工具中就能看到 pinia(一个菠萝图标)。

import {createApp} from 'vue'
import App from './App.vue'
import router from './router'

// 引入
import { createPinia } from 'pinia'

const app = createApp(App)

// 创建
const pinia = createPinia()
app.use(router)

// 安装:就像安装 vue-router 一样使用
app.use(pinia)
app.mount('#app')

vue3 快速入门系列 —— 状态管理 pinia

有时这个菠萝没出现,可以关闭浏览器或重启服务。

Tip: 详细请看 pinia 安装官网

第一个示例

vuex 的核心概念有 State、Getters、Mutations、Actions和Modules。其中 State 是数据,我们不能直接修改数据。

pinia 比 vuex 更轻量,更易使用。比如拿到数据后就能直接改,符合直觉

请看示例:

pinia 的数据从项目目录上说,会放在 store 文件夹中。

通常我们会对状态进行分类,比如用户相关的数据放在 store/user.ts 中:

// src/store/user.ts
import { defineStore } from 'pinia'

// 你可以任意命名 `defineStore()` 的返回值,但最好使用 store 的名字,同时以 `use` 开头且以 `Store` 结尾。
// (比如 `useUserStore`,`useCartStore`,`useProductStore`)
// 第一个参数是你的应用中 Store 的唯一 ID。 Pinia 将用它来连接 store 和 devtools
export const useUserStore = defineStore('user', {
  // actions 里面放一个一个的方法,用于响应组件中的动作
  actions: {
    changeNameAndAge() {
      // this Proxy(Object)
      // 里面有 $state。在 vue2 中有 $watch、$on等以$开头的都是给程序员用的实例方法
      console.log('this', this);
      
      // 没必要通过 $state,直接访问即可
      this.name += '~'
      this.$state.age += 1
    }
  },
  state: () => {
    return {
      name: 'peng',
      age: 18,
    }
  },
})

通过 defineStore 定义一个 store,第一个参数是 store 的id,命名建议规范,例如使用文件名,导出方式这里选择分别导出,导出的名字使用 use+user+store。

state 是一个函数,返回的就是数据

actions 中是一个一个的方法,但不需要像 vuex 中需用 dispatch 触发。

接着在需要使用状态的地方使用。读取状态的方式有2种,修改状态的方式有3种:

// Home.vue
<template>
  <div>
    <!-- 读取方式1 -->
    <p>{{ userStore.name }}</p>
    <!-- 读取方式2。方式1更方便 -->
    <p>{{ userStore.$state.age }}</p>

    <p><button @click="changeNameAndAge">修改方式1:change age and name</button></p>
    <p><button @click="changeNameAndAge2">修改方式2:change age and name</button></p>
    <p><button @click="changeNameAndAge3">修改方式3:change age and name</button></p>
  </div>
</template>

<script lang="ts" setup name="App">
// 写 '@/store/user.ts' vscode 报错:An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled
// 去掉 .ts 即可
import {useUserStore} from '@/store/user'

const userStore = useUserStore()
// userStore: Proxy(Object)
console.log('userStore: ', userStore);

function changeName() {
  // 修改数据方式1:直接操作数据
  // vue2中的vuex必须通过mutation更新数据,不能直接修改数据
  userStore.name += '~'
}

function changeNameAndAge() {
  userStore.$state.name += '~'
  userStore.$state.age += 1
}

function changeNameAndAge2() {
  // $patch 用于批量修改
  // patch 中文“碎片”,比如age 就是 pinia 中一个数据碎片
  userStore.$patch({
    name: userStore.name + '~',
    age: userStore.age + 1
  })
}

function changeNameAndAge3() {
  // 调用 actions
  userStore.changeNameAndAge()
}
</script>

Tip: changeNameAndAge 会触发两次修改,而 changeNameAndAge2 使用 $patch 会进行批量修改,从开发者时间线中看到,只执行一次。如果很多数据同时修改,推荐使用 patch。

优雅的读取数据

前面我们是这么读取 store 中数据:

<p>{{ userStore.name }}</p>

const userStore = useUserStore()

如果需要读取的数据太多,在模板中就会出现很多 userStore,于是我们想到用 toRefs 解构解决。就像这样:

<p>优雅的读:{{ name }}</p>

import {toRefs} from 'vue'
const userStore = useUserStore()
const {name} = toRefs(userStore)

但是 toRefs(userStore) 太重,通过console.log(toRefs(userStore)) 你会发现toRefs将 store 所有属性(包括方法)都转成 ref,其实我们只需要将数据转成 ref 即可。

pinia 也想到了这个问题,于是可以用 storeToRefs 替代。就像这样:

<p>优雅的读:{{ name }}</p>

import {storeToRefs} from 'pinia'
const userStore = useUserStore()

const {name} = storeToRefs(userStore)

// storeToRefs(userStore): {name: ObjectRefImpl, age: ObjectRefImpl}
console.log('storeToRefs(userStore): ', storeToRefs(userStore));

// toRefs(userStore): {$id: ObjectRefImpl, $onAction: ObjectRefImpl, $patch: ObjectRefImpl, $reset: ObjectRefImpl, $subscribe: ObjectRefImpl, …}
console.log('toRefs(userStore): ', toRefs(userStore));

Getters

和 vuex 中 Getters 作用相同,用法类似。

这里用了两种方式定义 getters:

  state: () => {
    return {
      name: 'Peng',
      age: 18,
    }
  },
  getters: {
    // 推荐使用箭头函数,参数会传入 state
    bigName: (state) => state.name.toLocaleUpperCase(),

    // 如果需要访问其他 getters 属性,可以通过非箭头函数,通过 this 访问
    lowerName2(): string{
      return this.bigName.toLocaleLowerCase()
    }
  },

数据取得的方式和 state 相同:

<p>优雅的读:{{ name }}</p>
<p>bigName:{{ bigName }}</p>
<p>lowerName2:{{ lowerName2 }}</p>

const userStore = useUserStore()

const {name, bigName, lowerName2} = storeToRefs(userStore)

Tip:详细请看 pinia getters

订阅

类似于 Vuex 的 subscribe 方法,你可以通过 store 的 $subscribe() 方法侦听 state 及其变化

只要 userStore 中的数据变化了,函数就会被调用,我们通常关心第二个参数:

// 只要 userStore 数据变化,这个
userStore.$subscribe((mutation, state) => {
  // {storeId: 'user', type: 'direct', events: {…}}
  console.log('mutation: ', mutation);

  // Proxy(Object) {name: 'Peng~', age: 19}
  console.log('state: ', state);

  // 每当状态发生变化时,将整个 state 持久化到本地存储。
  localStorage.setItem('userStore', JSON.stringify(state))
})

我们可以将 state 存储到本地,这样就可以实现页面刷新,状态不丢失。

Tip: 细节请看 订阅 state。

组合式写法

目前 actions state 写法属于声明式的:

import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  actions: {
    changeNameAndAge() {
      this.name += '~'
      this.$state.age += 1
    }
  },
  state: () => {
    return {
      name: 'Peng',
      age: 18,
    }
  },
  getters: {
    bigName: (state) => state.name.toLocaleUpperCase(),
    lowerName2(): string{
      return this.bigName.toLocaleLowerCase()
    }
  },
})

将其改成组合式。代码如下:

import { defineStore } from 'pinia';
import {ref, computed} from 'vue'
export const useUserStore = defineStore('user', () => {
  // 数据用 ref 或 reactive 定义
  const name = ref('Peng')
  const age = ref(18)
  
  // getters 用计算属性
  const bigName = computed(() => name.value.toLocaleUpperCase())
  const lowerName2 = computed(() => bigName.value.toLocaleLowerCase())

  // actions 用方法定义
  function changeNameAndAge() {
    name.value += '~';
    age.value += 1;
  }

  // 最后必须暴露出去
  return {
    // vscode 中数据一个颜色、方法另一个颜色
    name,
    age,
    bigName,
    lowerName2,
    changeNameAndAge,
  };
});

Tip:组合式写法更灵活(请看 组合式 Store),层级少,但必须返回。具体如何选择自行决定。

扩展

ref 数据要不要 .value

const a = reactive({
    x: 1,
    y: 2,
    z: ref(3)
})

const b = ref(4)
console.log(a.x)
// ref 如果在里面,则不需要拆包
console.log(a.z)
console.log(b.value)

读取响应式对象中的 ref 不需要 .value

其他章节请看:

vue3 快速入门 系列

到了这里,关于vue3 快速入门系列 —— 状态管理 pinia的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vue2(Vuex)、vue3(Pinia)、react(Redux)状态管理

    Vuex 是一个专为 Vue.js应用程序开发的状态管理模式。它使用集中式存储管理应用的所有组件的状态,以及规则保证状态只能按照规定的方式进行修改。 State(状态) :Vuex 使用单一状态树,即一个对象包含全部的应用层级状态。这个状态树对应着一个应用中的所有状态。 Gett

    2024年01月23日
    浏览(48)
  • Vite4+Typescript+Vue3+Pinia 从零搭建(6) - 状态管理pina

    项目代码同步至码云 weiz-vue3-template pina 是 vue3 官方推荐的状态管理库,由 Vue 核心团队维护,旨在替代 vuex。pina 的更多介绍,可从 pina官网 查看 更简洁直接的 API,提供组合式风格的 API 支持模块热更新和服务端渲染 对TS支持更为友好 src目录下新建store文件夹,并新建index.t

    2024年02月05日
    浏览(83)
  • 从零开始Vue3+Element Plus后台管理系统(六)——状态管理Pinia和持久化

    官网:https://pinia.vuejs.org/zh/ Pinia 是 Vue 的专属状态管理库,相比Vuex更好用,优点不多了说官网有,用起来最重要! 在应用的根部注入创建的 pinia 定义store,拿用户登录举个简单例子 在src目录新建文件夹store,然后新建文件user.ts 在Vue页面中使用Pinia 如果我们把登录用户的信息

    2024年02月05日
    浏览(46)
  • vue3中状态管理库pinia的安装和使用方法介绍及和vuex的区别

    Pinia 与 Vuex 一样,是作为 Vue 的“状态存储库”,用来实现 跨页面/组件 形式的数据状态共享。它允许你跨组件或页面共享状态。如果你熟悉组合式 API 的话,你可能会认为可以通过一行简单的 export const state = reactive({}) 来共享一个全局状态。 当该数据、方法在很多地方都需要

    2024年01月20日
    浏览(44)
  • vue3 快速入门系列 —— vue3 路由

    在vue3 基础上加入路由。 vue3 需要使用 vue-router V4 ,相对于 v3,大部分的 Vue Router API 都没有变化。 Tip :不了解路由的同学可以看一下笔者之前的文章:vue2 路由 参考:vue2 路由官网、vue3 路由官网 在 Vue Router API 从 v3(Vue2)到 v4(Vue3)的重写过程中,大部分的 Vue Router API 都

    2024年04月09日
    浏览(46)
  • vue3 快速入门系列 —— 基础

    前面我们已经用 vue2 和 react 做过开发了。 从 vue2 升级到 vue3 成本较大,特别是较大的项目。所以许多公司对旧项目继续使用vue2,新项目则使用 vue3。 有些UI框架,比如ant design vue1.x 使用的 vue2。但现在 ant design vue4.x 都是基于 vue3,示例默认是 TypeScript。比如 table 组件管理。

    2024年04月08日
    浏览(44)
  • vue3 快速入门系列 —— 组件通信

    组件通信在开发中非常重要,通信就是你给我一点东西,我给你一点东西。 本篇将分析 vue3 中组件间的通信方式。 Tip :下文提到的绝大多数通信方式在 vue2 中都有,但是在写法上有一些差异。 在 vue3 基础上进行。 新建三个组件:爷爷、父亲、孩子A、孩子B,在主页 Home.vu

    2024年04月17日
    浏览(66)
  • Vue——状态管理库Pinia

    写在前面 :本文参考小满大牛的pinia专栏 Vuex 和 Pinia 均是 Vue.js 的状态管理库,它们为 Vue 应用程序提供了一种集中式的、可预测的状态管理解决方案。 Vuex 是 Vue.js 官方推荐的状态管理库之一。它的核心概念包括 state、mutation、action 和 getter。其中,state 代表应用程序的状态

    2024年02月07日
    浏览(43)
  • Vue状态管理库-Pinia

    Pinia 是 Vue 的专属状态管理库,它允许支持跨组件或页面共享状态,即共享数据,他的初始设计目的是设计一个支持组合式API的 Vue 状态管理库(因为vue3一个很大的改变就是组合式API),当然这并不是说Pinia只支持vue3,他是同时支持vue2和vue3的, 本文倾向于拥抱Vue3,所以代码语

    2024年02月22日
    浏览(55)
  • Vue使用 Pinia 进行状态管理

    Pinia 是一个适用于 Vue.js 的状态管理库,它采用了组合式 API 的理念,使得状态管理变得更加简单、直观和灵活。与传统的 Vuex 相比,Pinia 提供了更好的 TypeScript 支持,同时也更加适合大型应用程序和复杂状态逻辑的管理。 首先,我们需要在 Vue 项目中安装 Pinia。你可以通过

    2024年02月13日
    浏览(66)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包