为什么 Pinia/Vuex 比具有服务类的经典方法更受青睐? [关闭]

2023-11-30

皮尼亚/Vuex

Pinia/Vuex 以及 Redux 被设计为“单一事实来源”,您可以拥有一个或多个存储来保存应用程序数据,并且可以从任何地方获取这些数据。

Pinia 商店如下所示:

export let useProductsStore = defineStore('products', () => {
    let data = ref(products);

    function getList (params) {
        return someSearchStuffForProducts(params);
    }

    return {data, getList};
});

然后可以用作:

let productsStore = useProductsStore();
console.log(data, data.value);
productsStore.getList(params);

我们可以创建多个商店:

let usersStore     = useUsersStore();
let productsStore  = useProductsStore();
let basketStore    = useBasketStore();
let favoritesStore = useFavoritesStore();

商店可以互相引用:

export let useUsersStore = defineStore('users', () => {
    let productsStore = useProductsStore();
}

export let useBasketsStore = defineStore('basket', () => {
    let productsStore = useProductsStore();
}

//Et cetera

最后,Pinia/Vuex 是提供检索和操作存储在状态中的数据的能力的工具。

经理/服务类

但还有另一种成熟的方法:管理器/服务类。

前面的例子可以重写为:

//Define the "single source of truth"
let store = {
    products:      { /* ... */},
    currentUser:   { /* ... */},
    userBasket:    { /* ... */},
    userFavorites: { /* ... */},
};

//Here goes manager classes
class ProductsManager {
    constructor (params) {
        this.state = params.state;
        //...
    }

    getList (params) {
        return someSearchStuffForProducts(params);
    }
}

class UsersManager {
    constructor (params) {
        this.state = params.state;
        //Products manager is injected as a dependency
        this.productsManager = params.productsManager;
        //...
    }
}

class BasketManager {
    constructor (params) {
        this.state = params.state;
        //Products manager is injected as a dependency
        this.productsManager = params.productsManager;
        //...
    }
}

//Some config/initialization script
export let DIC = {}; //Container for manager instances
DIC.productsManager = new ProductsManager({state: store.products});
DIC.usersManager = new usersManager({
    state:           store.currentUser,
    productsManager: DIC.productsManager,
});
DIC.basketManager = new BasketManager({
    state:           store.userBasket,
    productsManager: DIC.productsManager,
});

//Usage
import {DIC} from './config';
DIC.productsManager.getList();
DIC.basketManager.add(someProductId);
DIC.basketManager.changeCount(someProductId, 3);

所有这些都可以轻松地在 TypeScript 中输入,无需额外的包装器,ref(), etc.

讨论

据我所知,Pinia 看起来就像“重新发明轮子”:以笨拙的方式编写相同的功能。

此外,它不提供依赖项注入:您无法在配置中初始化存储并将一个存储准确地注入另一个存储,您必须将依赖项直接硬编码到存储中,方法是useProductsStore()等等。

继承或任何其他 OOP 的东西也是不可能的。

连松promotes循环依赖,导致意大利面条式代码,可维护性很差。

那么,归根结底,为什么人们应该更喜欢 Pinia/Vuex,而不是久经考验的、带有管理器类的干净的 OOP 方法呢?我已经花了几十个小时编写我自己发明的教程项目,使用 Pinia 作为“下一个推荐的 Vue 状态管理”,现在我很想将所有内容重写为管理器类,因为我发现 Pinia 笨拙且丰富。我只是记得几年前我正在编写另一个测试项目 - 使用 Vue2 - 当时我使用了管理器类 - 一切都很顺利。我是否忽略了什么?如果我放弃 Pinia 会有问题吗?


类在 Vue 反应性中是二等公民,并且存在一些陷阱。他们无法绑定this在构造函数中,这将导致使用非反应式类实例而不是反应式代理。他们无法有效地使用引用因为这些是打开的有记录但不正常的方式。他们无法使用 get/set 访问器来计算引用。这些问题需要显式使用 Vue 反应性 API 以奇怪的方式编写类,或者以受限制的方式设计类,因此reactive(new MyClass)不会阻止它正常工作。

类不具备商店所具有的功能,例如对 Vue 开发工具、插件系统等的广泛支持。

类在 JavaScript 中也是不可序列化的,因此保存和恢复状态需要自定义逻辑,而不是像存储持久性插件中那样进行简单的 JSON(反)序列化。

依赖注入并不是类所独有的,并且可以以合适的方式执行,例如Pinia 商店:

const basketManagerStore = defineStore({
  state: () => ({ _getFoo: null }),
  getters: { 
    foo: state => state._getFoo()
  },
  actions: {
    setFoo(getFoo) {
      this._getFoo = getFoo;
    }
  }
});

basketManagerStore.setFoo(useSomeFooStore);

在许多情况下,最好处理 Pinia 存储可组合项而不是存储实例,因为这可以解决循环依赖关系,如果过早调用可组合项,循环依赖关系可能会成为问题。类也可能出现同样的问题,并且需要使用 DI 容器而不是直接使用类实例。

继承不存在任何问题,因为可重用代码可以用 FP 而不是 OOP 来处理。 Vue 没有明确推广它,但使前者更惯用且使用起来更舒适。

TL;DR:坚持使用普通对象和 FP,因为这是 Vue 反应性设计的主要情况。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 Pinia/Vuex 比具有服务类的经典方法更受青睐? [关闭] 的相关文章

随机推荐

  • 有没有办法在不创建类实例的情况下获取类实例属性?

    这是我的第一个问题的链接 从字典创建类实例 所以我试图从字典创建类实例 该实例包含类没有的键 例如 class MyClass object def init self value1 value2 self attr1 value1 sel
  • excel:比较日期的vba类型不匹配

    我试图对两个日期 在不同列中 的年份和当前年份日期进行比较 如果年份相同 则应在相应行的第 13 列写入单词 ATUAL 如果年份不同 则不应写入任何内容 这是我到目前为止所尝试过的 Sub CopyColumn2 Dim i As Lon
  • dexguard 的实现

    我已将 com saikoa dexguard eclipse adt jar 文件放入 eclipse 的 dropin 文件夹中 并修改了 android 项目中的 Proguard Project 和 Project Properti
  • docker extra_host 参数需要主机名的字典值,如何使用变量?

    在 ansible playbook 中 docker 参数 extra host 包含两部分 主机 ip address 我试图将主机和 IP 地址作为变量传递 它们来自提示变量 我的主机文件中的最终结果是 1 2 3 4 server
  • 解析数据库授权 - 用户对象的安全性

    我有一个 ASP NET MVC 4 Web 应用程序 我在后端使用 Parse 作为数据库 https www parse com 和 C 作为编程语言 我使用 ParseUser 类来登录注册用户 https www parse com
  • 逆透视 Excel 矩阵/数据透视表?

    有没有一种快速的方法来 取消透视 Excel 矩阵 数据透视表 在 Excel 或其他地方 无需编写宏或其他代码 同样 我可以自己编写代码 C 或 VBA 或其他 来执行此操作 我想知道是否可以做到without代码 快点 例如 我需要转换
  • fopen 用于写入但不独占

    我想用fopen file w 打开文件进行写入但不独占 IE 我想让另一个进程在文件仍然打开时读取该文件 请注意 我在每行之后都会进行同花 这样我就不会错过任何内容 当其他进程从文件读取时 写入将处于空闲状态 该文档没有提到排他性 但实验
  • 检测到 CallbackOnCollectedDelegate

    当我的代码运行 5 10 分钟后 我不断收到此错误 检测到 CallbackOnCollectedDelegate 消息 对 CashRecyclerTestapp MessageMonitor NativeMethods WndProc
  • 尝试对自定义 JavaScript 对象进行排序

    我不太擅长 JS 但到目前为止还幸存下来 我正在创建一个复杂的 JS 对象并想要对其进行排序 该对象的结构如下所示 cart attributes Attribute Value 我正在创建一个独特的属性 它告诉我由冒号任意分隔的 3 件事
  • Ubuntu Python“没有名为 paramiko 的模块”

    所以我尝试在 Ubuntu 上使用 Python 2 7 使用 Paramiko 但是 import paramiko 会导致此错误 Traceback most recent call last File
  • 在excel vba中使用数组或字典作为sql中的from子句

    是否可以使用数组或字典作为 SQL 语句中的表 例如 strSQL SELECT FROM myArray 提前致谢 扩展 Nathan Sav 提供的想法 以下代码应该 Dim a 3 As String a 0 1 as C1 a 1
  • 在 Git 中仅提交文件的部分更改

    当我在 Git 中更改文件时 如何才能仅提交部分更改 例如 如何仅提交文件中已更改的 30 行中的 15 行 您可以使用 git add patch
  • Scala:用最后一个非空值填充列表中的空白

    我有一个类似的列表 val arr Array a b c 我正在寻找一种方法来创建 Array a a a b c c 您可以尝试使用折叠 简单 易于理解 的方法是向左折叠 Array empty String arr case prev
  • 如何打开 Excel 工作簿而不显示消息 该工作簿包含指向其他数据源的链接。以编程方式?

    我想以编程方式打开 1 个或多个 Excel 工作簿 当我打开工作簿时 你会得到一个问题 该工作簿包含其他数据源的链接 我不想按 不更新 您如何离开此消息框 所以功能不会再中断 不需要更新 尝试放入工作簿打开事件处理程序 Applicati
  • InternalsVisibleTo 的替代方案

    我目前正在尝试在我的解决方案中编写单元测试 但我想将单元测试放在不同的单独项目中 问题是当我生成一些假测试数据时 我需要设置类的属性 但这是不可能的 因为属性具有私有 内部设置 我找到了一种使用属性仅向某些项目公开内部属性的方法Intern
  • 如何获取生成的 java 进程的 PID

    我正在编写几个 java 程序 在完成我想做的任何事情后 需要在单独的 JVM 中杀死 清理 为此 我需要获取我正在创建的 java 进程的 PID jps l可在 Windows 和 Unix 上运行 您可以使用 java 程序调用此命令
  • 带 url 重定向的 Rails 句柄 404

    我希望使用 Rails 将链接重定向到互联网上 我确信这些链接从我的旧域到新域 我想使用地址 example com about about 将不再存在 在我的 application controller 中获取 404 检查 url 然
  • NSDate 因连续操作而崩溃

    我下面有以下代码 旨在将名为 today 的类变量向前或向后更改一天 它会工作一次 但之后就会崩溃 无论我按左键还是右键 它都会做同样的事情 我究竟做错了什么 今天的 var 是一个类 var 发起为 today NSDate date 这
  • VBA Powerpoint - 如何突出显示选定的文本

    我想将所选文本突出显示为某种颜色 但这不起作用 你能帮我吗 Sub ShadingLtYellow ActiveWindow Selection TextRange HighlightColor RGB RGB 255 255 175 En
  • 为什么 Pinia/Vuex 比具有服务类的经典方法更受青睐? [关闭]

    Closed 这个问题是基于意见的 目前不接受答案 皮尼亚 Vuex Pinia Vuex 以及 Redux 被设计为 单一事实来源 您可以拥有一个或多个存储来保存应用程序数据 并且可以从任何地方获取这些数据 Pinia 商店如下所示 ex