如何进一步扩展扩展的Javascript类模块的状态



我正在减少体积过大、过于复杂的Vuex存储模块。我们的状态管理系统是使用JS类使用Vuex构建的,其中我们有一个扩展到多个其他更具体模块的基本模块。我目前正在重构其中一个更"特定"的模块——这个模块处理包含少数组件的几个视图的状态。我正试图像我们所有其他模块一样扩展这个模块,并使用扩展语法引入现有的状态属性…

export default class ChildModule extends BaseModule {
constructor() {
super()
this.state = {
...this.state
}
this.getters = {
...this.getters
}
}
// ** the same syntax for actions and mutations 

// logging rootState in an action inside GrandchildModule correct values from ChildModule
}

工作模块和坏模块的唯一区别是正在扩展的类…

export default class GrandchildModule extends ChildModule {...

出于某种原因,我还没有弄清楚GrandchildModule没有从需要从api获取数据的ChildModule属性继承状态-不需要api访问的属性运行正常-我在GrandchildModule中使用getter失败了,我希望它能对获取的数据做出反应?

我希望有人能对我如何做到这一点有一些见解,或者告诉我做错了什么

更新:在我目前正在调查的反应性上发现了这一点——不是100%这是我的问题,但可能是吗?

示例结构-带有js类的stackblitz

更新的stackblitz

您共享的stackblitz的第一个问题是,在每个类(除了BaseClass)中,您将state扩展到constructor中。并且未定义CCD_ 7。你可能是指this.state:

export default class ChildClass extends BaseClass {
constructor() {
super();
this.state = {
...this.state,
name: 'ChildClass',
};
}
}

第二,在index.js中,您试图显示GreatGrandchild.id,但它同样不存在。GreatGrandchild是一个JavaScript类声明(从技术上讲,它是一个具有单个属性的函数:name——类的实际名称),因此它没有id。即使是它的实例(在您的案例中为timmy)也没有id。但他们确实有state.id

为了更好地理解JavaScript类是如何工作的,我推荐MDN。

如果要引用继承的state.id(来自BaseClass > ChildClass > GrandchildClass > GreatGrandchild),可以使用:

const timmy = new GreatGrandchild();
console.log(timmy.state.id); // output: 0

看到它在这里工作。


从您发布的示例来看,尚不清楚您的代码与vuex的关系。或者vue。您可能希望提供一个最低限度的可运行示例。

然而,根据一般原则,我不建议扩大Vuex商店。一旦存储被实例化,添加到其stateactionsmutationsgetters的新成员将不会是被动的。如果你决心走这条路,这个问题可能会有所帮助。

适用于您的案例的是BaseClass,它实际上并没有创建商店,但持有常见的商店道具,然后拥有不同的商店类,这些商店类在将基类的道具与自己的道具合并后实际创建商店。大致如下:

class BaseStore {
constructor() {
// place here what you want defined on all stores
this.state = {
// ...
};
this.actions = {
// ...
};
this.getters = {
// ...
};
this.mutations = {
// ...
};
}
}
class SomeStore extends BaseStore {
constructor({ state = {}, mutations = {}, actions = {}, getters = {} }) {
super();
return new Vuex.Store({
state: {
...this.state,
...state,
},
actions: {
...this.actions,
...actions,
},
getters: {
...this.getters,
...getters,
},
mutations: {
...this.mutations,
...mutations,
},
});
}
}
class SomeOtherStore extends BaseStore {
constructor({ state = {}, mutations = {}, actions = {}, getters = {} }) {
super();
return new Vuex.Store({
state: {
...this.state,
...state,
},
actions: {
...this.actions,
...actions,
},
getters: {
...this.getters,
...getters,
},
mutations: {
...this.mutations,
...mutations,
},
});
}
}
// declare or import state, actions, getters, mutations, otherState, otherActions, otherMutations and otherGetters
const myFirstStore = new SomeStore({
state,
actions,
getters,
mutations
});
const myOtherStore = new SomeOtherStore({
state: otherState,
actions: otherActions,
mutations: otherMutations,
getters: otherGetters
})

尽管上述模式是可能的,但我对其在现实世界场景中的有用性持怀疑态度。我并不推荐它。主要原因是当你想处理同一个类的多个实例时,类是有用的。很难想象在一个场景中,拥有同一商店的多个实例会很有用。


注意:我使用了Vuex 3实例化方法,因为我猜您使用的是Vue2+Vuex 3。如果使用Vue 3+Vuex 4,则应将new Vuex.Store()替换为createStore()


另一个注意事项:上面的例子可以在不使用类的情况下编写。我认为它有点干净:

const defaultStoreProps = {
state: {
// common state
},
actions: {
// common actions
},
// etc...
}
const myFirstStore = new Vuex.Store({
state: {
...defaultStoreProps.state,
// other state
},
actions: {
...defaultStoreProps.actions,
// other actions
},
// etc...
})
const mySecondStore = new Vuex.Store({
state: {
...defaultStoreProps.state,
// other state
},
actions: {
...defaultStoreProps.actions,
// other actions
},
// etc...
})

最新更新