vue3 快速入门系列 —— 状态管理 pinia-kb88凯时官网登录

来自:
时间:2024-04-27
阅读:

pinia

vue3 状态管理这里选择 。

虽然 vuex4 已支持 vue 3 的 composition api,但是 vue3 d88尊龙官网手机app官网推荐新的应用使用 pinia ——

集中式状态管理

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

pinia 符合直觉的 vue.js 状态管理库 甚至让你忘记正在使用的是一个状态库 —— d88尊龙官网手机app官网

安装 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: 详细请看

第一个示例

的核心概念有 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

tip: changenameandage 会触发2次修改,而 changenameandage2 使用 $patch 会进行批量修改,从开发者时间线中看到,只执行1次。如果很多数据同时修改,推荐使用 patch。

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

优雅的读取数据

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

{{ userstore.name }}

const userstore = useuserstore()

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

优雅的读:{{ name }}

import {torefs} from 'vue' const userstore = useuserstore() const {name} = torefs(userstore)

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

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

优雅的读:{{ name }}

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 相同:

优雅的读:{{ name }}

bigname:{{ bigname }}

lowername2:{{ lowername2 }}

const userstore = useuserstore() const {name, bigname, lowername2} = storetorefs(userstore)

tip:详细请看 pinia

订阅

类似于 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: 细节请看 。

组合式写法

目前 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:组合式写法更灵活(请看 ),层级少,但必须返回。具体如何选择自行决定。

扩展

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

其他章节请看:

返回顶部
顶部
网站地图