Pinia/Vuex

Pinia/Vuex和Redux都被设计成"单一的真理来源",在那里你有一个或多个store 保存应用程序数据,从任何地方都可以获得.

一家Piniastore 看起来是这样的:

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);

我们可以创建多个store :

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

store 之间可以相互指代:

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);

所有这些都可以很容易地以打印稿的形式输入,而不需要额外的包装器、ref()等.

讨论

在我看来,Pinia看起来就像是"重新发明了轮子":以一种笨拙的方式编写了相同的功能.

此外,它不提供依赖注入:您不能在配置中注入存储并准确地将一个存储注入到另一个存储中,您必须将依赖项直接硬编码到存储中,按useProductsStore()或类似的方式编码.

继承或任何其他面向对象的东西也是不可能的.

Pinia甚至promotes个循环依赖,这导致了可维护性较差的意大利面代码.

那么,毕竟,为什么人们应该更喜欢Pinia/Vuex,而不是经过战斗考验的、干净的OOP方法和经理类?我已经花了几十个小时编写我自己发明的教程项目,使用Pinia作为"Vue的下一个推荐的状态管理",现在我很想把所有东西重写到Manager类中,因为我发现Pinia既笨拙又丰富.我只是回忆起几年前我在编写另一个测试项目时--使用Vue2--当时我使用的是管理器类--一切都很顺利.我是不是忽略了什么?如果我放弃皮尼亚,我会有问题吗?

推荐答案

在Vuereact 性方面,阶级是二等公民,有一些trap .这将导致使用非react 性类实例而不是react 性代理.它们是cannot efficiently use refs的,因为这些是用documented but abnormal way打开的.它们不能使用计算引用的Get/Set访问器.这些问题要求要么以一种奇怪的方式编写一个显式使用Vuereact API的类,要么以一种受限的方式设计一个类,因此reactive(new MyClass)不会阻止它正常工作.

类没有store 所具有的功能,比如对Vue DevTool、插件系统等的广泛支持.

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

依赖项注入不是类独有的,可以以合适的方式执行,例如,对于Piniastore :

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,因为这是Vuereact 性设计的主要目标.

Vue.js相关问答推荐

在VueJS中卸载元素之前是否应该删除JavaScript事件收件箱?

Pinia+Vue 3状态react 性-StoreToRef的替代方案

如何使用composition api v-model Select 框获取其他JSON 值?

Vue CLI: 如何在一个vtextfield更改时让另一个vtextfield的值也同时更改,但同时又可以覆盖它?

将 v-calendar 与以时间和日期格式出现的事件一起使用

vue3 + pinia:如何从?store 中获取一个值

处理多张卡片中的按钮

在重复表行中

vuejs vue-cli 如何使用 console.log 而不会出现任何错误

在 VueJS 中存储图像的正确位置是什么 - 公共文件夹或assets文件夹?

Eslint Vue 3 解析错误:'>' expected.eslint

正确使用 Vue $refs

确保在渲染组件之前加载 Vuex 状态

vue js 组件中的 this.$route 只返回 undefined

可以同时使用 Tailwind css 和 Bootstrap 4 吗?

删除一行后刷新 Bootstrap-Vue 表

异步方法不等待函数

Vue.js react性如何在幕后工作?

如何访问通用 javascript 模块中的当前路由元字段

如何在 vue3 中的setup方法中发出事件?