vue:状态管理库及其部分原理(Vuex、Pinia)

1、为什么要用状态管理库?

多组件的状态共享问题: 当多个组件需要访问和修改相同的数据时,我们需要在组件之间传递 props或者使用事件总线。当,应用就会变得难以维护和调试。

多组件状态同步问题: 当一个组件修改了状态,其他组件可能无法立即得知该变化。

状态变更的追踪问题: 无法追踪到状态的变化是由何处引起的,使得调试和维护变得困难。

2、Vuex

2.1、核心概念

2.1.1、State:用于存储应用程序的状态数据

当你需要在多个组件之间共享数据时,可以将这些数据放入state中。

例如,保存用户登录状态、购物车中的商品列表等。

可以通过在组件中使用store.state.xxx或计算属性来获取状态数据。

2.1.2、Mutation:用于修改状态的方法,必须是同步函数。

什么时候用? 当你需要修改状态时。让所有的状态变更都经过 mutation可以保证状态的变更是可追踪的。

通常,一个 mutation 对应一个状态变更操作。例如,修改用户登录状态、添加商品到购物车等。

2.1.3、Action:用于处理异步逻辑或提交多个 mutation。

什么时候用? 当你需要处理异步操作(例如发起网络请求)或需要在一个 action 中提交多个 mutation 时。

Action 可以包含任意的异步操作,并可以通过提交 mutation 来修改状态。

例如,获取用户信息的异步请求、添加多个商品到购物车等。

2.1.4、Getter:用于从状态中获取派生数据的方法。

什么时候用? 当你需要根据状态state.xxx计算出一些数据时。

Getter 可以将一些复杂的数据计算逻辑封装起来,并在组件中使用 store.getters 来获取计算后的数据。

例如,基于购物车商品列表计算购物车总价、根据用户权限判断是否具有管理员角色等。

2.2、原理(v4.0.2)

2.2.1、vuex如何挂载到vue实例的

install (app, injectKey) {
   
  // 使用`vue.provide()`将`vuex`提供给整个应用
  app.provide(injectKey || storeKey, this)
  // 将vuex实例赋值给vue.$store;
  // 在项目的非setup中可以使用this.$store.state.xxx取值就是这样来的
  app.config.globalProperties.$store = this
}

2.2.2、useStore 源码

import {
    inject } from 'vue'

export const storeKey = 'store'

export function useStore (key = null) {
   
  return inject(key !== null ? key : storeKey)
}

commit源码

  commit (_type, _payload, _options) {
   
    const {
    type, payload, options } = unifyObjectStyle(_type, _payload, _options)

    const mutation = {
    type, payload }
    // 查找该类型对应的 mutations
    const entry = this._mutations[type]
    if (!entry) {
   
      return
    }
    // 执行mutations对应的处理函数
    this._withCommit(() => {
   
      entry.forEach(function commitIterator (handler) {
   
        handler(payload)
      })
    })

    // 通知订阅者
    this._subscribers
      .slice() // shallow copy to prevent iterator invalidation if subscriber synchronously calls unsubscribe
      .forEach(sub => sub(mutation, this.state))
  }

3、Pinia

相比vuex的优势:

  • 可通过devtools追踪数据变化,无需通过commit提交Mutation
  • 支持TS,提供代码自动补全,源码为TS编写;vuex是用JS编写的,vuex要支持TS需要安装插件
  • pinia更轻,大小只有 1kb 左右

改变状态的方法

  • 直接修改变量
  • 调用action
  • 调用patch

3.1原理

install 原理与vuex一致

  	let toBeInstalled: PiniaPlugin[] = []
    install(app: App) {
   
      if (!isVue2) {
   
        pinia._a = app
        // 暴露pinia,组件通过inject注入pinia实例
        app.provide(piniaSymbol, pinia)
        // 模版中可通过$pinia访问
        app.config.globalProperties.$pinia = pinia
        // 将pinia的plugin 存到插件列表
        toBeInstalled.forEach((plugin) => _p.push(plugin))
        toBeInstalled = []
      }
    },

pinia的plugin实现原理
1、在调用vue.use(pinia)之前注入插件的情况,会将plugin存放到toBeInstalled列表,
2、调用vue.use(pinia)之后,会将toBeInstalled的插件存到pinia实例的_p中
3、调用useStore时将plugin注入每个Store实例

    pinia.use(plugin) {
   
      if (!this._a && !isVue2) {
   
        toBeInstalled.push(plugin)
      } else {
   
        _p.push(plugin)
      }
      return this
    }
useStore(pinia) {
   
 if (!pinia._s.has(id)) {
   
      // creating the store registers it in `pinia._s`
      if (isSetupStore) {
   
        createSetupStore(id, setup, options, pinia)
      } else {
   
        createOptionsStore(id, options as any, pinia)
      }

      /* istanbul ignore else */
      if (__DEV__) {
   
        // @ts-expect-error: not the right inferred type
        useStore._pinia = pinia
      }
    }
}
createSetupStore () {
   
	pinia._p.forEach((extender) => {
   
		assign(
        store,
        scope.run(() =>
          extender({
   
            store: store as Store,
            app: pinia._a,
            pinia,
            options: optionsForPlugin,
          })
        )!
      )
	}}

相关推荐

  1. vue状态管理及其部分原理Vuex、Pinia)

    2024-01-19 12:36:02       50 阅读
  2. vue状态管理

    2024-01-19 12:36:02       41 阅读
  3. VuexVue.js 的状态管理

    2024-01-19 12:36:02       34 阅读
  4. Pinia|VUe状态管理

    2024-01-19 12:36:02       58 阅读
  5. Pinia:一个Vue状态管理

    2024-01-19 12:36:02       55 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-01-19 12:36:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-01-19 12:36:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-01-19 12:36:02       82 阅读
  4. Python语言-面向对象

    2024-01-19 12:36:02       91 阅读

热门阅读

  1. 安卓之文本转视频的应用场景以及技术优劣分析

    2024-01-19 12:36:02       60 阅读
  2. RTC讲解

    RTC讲解

    2024-01-19 12:36:02      54 阅读
  3. 【数据结构】平衡树

    2024-01-19 12:36:02       37 阅读
  4. spring boot集成loback日志配置

    2024-01-19 12:36:02       44 阅读
  5. spring中的事务及底层原理

    2024-01-19 12:36:02       68 阅读
  6. 高质量的前端代码

    2024-01-19 12:36:02       46 阅读
  7. flutter qr_flutter二维码库填充不满问题解决方案

    2024-01-19 12:36:02       61 阅读
  8. python 小说下载

    2024-01-19 12:36:02       51 阅读