Pinia 和 Vuex 的对比

目录

  • [1,Pinia 介绍](#1,Pinia 介绍)
  • [2,和 Vuex 的对比](#2,和 Vuex 的对比)
  • [3,storeToRefs 源码分析](#3,storeToRefs 源码分析)

1,Pinia 介绍

官网简介

Pinia 使用上的问题,官方文档很详细,这里不做赘述。

  1. Pinia 是 Vue 的专属状态管理库,支持vue2和vue3,不能应用于其他前端框架。
  2. Pinia 是 Vue 官方团队的成员实现的,原本是为了探索 vue5.x 的可能性,后来发现已经实现了 vue5.x 的提案。所以就作为最新版本的 Vuex ,也就是下一代状态管理库来使用了。

2,和 Vuex 的对比

  1. 删除了 mutations ,只保留了 stategettersactions异步修改 state 现在可以放到 actions 中了。
  2. 不再有模块嵌套,只有 store(状态仓库)的概念,store 之间独立又可相互调用。
  3. 支持插件扩展,比如为 store 新增属性或方法,操作 action 等。
  4. 因为 Pinia 使用 TS 开发的,所以对 TS 有很好的支持。
  5. 兼容 vue2 和 vue3,同时支持选项式风格和组合式风格。
  6. 轻量,压缩后体积只有 1kb 左右。

在使用上,同样应避免直接操作 store,尽量都集中使用 actions 中的方法来操作 store 的状态。

3,storeToRefs 源码分析

在组件中使用 store 的属性时,会有一个问题:

html 复制代码
<script setup>
import { useCounterStore } from '@/stores/counter'

const store = useCounterStore()
// ❌ 这将不起作用,因为它破坏了响应性,这就和直接解构 `props` 一样
const { name, doubleCount } = store 

// ✅ 这样写是响应式的,当然也可直接使用 `store.doubleCount`
const doubleValue = computed(() => store.doubleCount)

// ✅ 作为 action 的 increment 可以直接解构
const { increment } = store
</script>

这时需要使用 storeToRefs(),它将为每一个响应式属性创建引用。

html 复制代码
<script setup>
import { useCounterStore } from '@/stores/counter'
import { storeToRefs } from 'pinia'

const store = useCounterStore()
const { name, doubleCount } = storeToRefs(store)
</script>

源码

js 复制代码
import { toRaw, ref, isVue2, isRef, isReactive, toRef, toRefs } from 'vue-demi';
/**
 * @param store - defineStore 定义的 store 对象
 */
function storeToRefs(store) {
    if (isVue2) {
        return toRefs(store);
    }
    else {
        store = toRaw(store);
        const refs = {};
        for (const key in store) {
            const value = store[key];
            if (isRef(value) || isReactive(value)) {
                refs[key] = toRef(store, key);
            }
        }
        return refs;
    }
}

原理其实很简单,我们在解构 props 时,直接解构也会失去响应式。需要使用 toRef 与其源属性保持同步。

所以 storeToRefs 的原理:遍历 store 中的响应式属性(跳过了 action),并使用 toRef 处理后返回新对象,这样解构新对象得到的属性会和 store 的源属性保持同步,而不失去响应式。

js 复制代码
const store1 = reactive({
  a: ref(1),
});
const store2 = toRaw(store1);
const _a = toRef(store2, "a");
_a.value++;
console.log(store1.a); // 2

以上。

相关推荐
怕浪猫5 小时前
FDE 如何正确解决现场项目工程性的问题
前端·后端·ai编程
西瓜太郎12345 小时前
外层模型卡片与分组详情成功率不一致,应该怎么排查?
前端·typescript·go·软件工程·react
GreenTea6 小时前
vLLM 与 SGLang KV Cache 底层实现机制深度调研报告
前端·后端·算法
毕业设计7038 小时前
(免费领源码) 基于微信小程序的预制菜商城的设计与实现25172-java、PHP、python、C#、小程序、大数据、单片机、网络工程等)
vue.js·python·mysql·微信小程序·pycharm·微信开发者工具·推荐算法
xifangge20258 小时前
AGENTS.md 怎么写?涵盖 Java、Python、Vue、Go 的 8 套开箱即用模板
java·vue.js·python
几何心凉8 小时前
没有万能模型:我用 AiiOnly Token Plan,把多款大模型的长处拼进同一个项目
前端
kyriewen9 小时前
Claude Code 的额度今天缩水了17%——官方公告上写的是"永久提高25%"
前端·ai编程·claude
雪芽蓝域zzs9 小时前
vue解构平铺VS对象包裹
前端·javascript·vue.js
风骏时光牛马10 小时前
从零到实战,完整AI学习路线
前端
三十而立洋11 小时前
深入理解 Monorepo:子包安装依赖
前端·前端工程化