首页 > 解决方案 > 如何在单独的文件中编写 mobx 操作方法并将它们导入具有可观察变量的实际 mobx 类?

问题描述

我有一个 mobx 类,它有一个名为 dataObject 的可观察变量。这个可观察变量是一个对象,它的结构是:

{
   name:string;
   dataType:string;
   value: string;
   description:string;
   .
   .
   .
   .
   . 
   ..... total around 45 such properties
}

每个对象属性都有一个操作方法来更新它。例如

@action updateName = (name:string) =>{
   this.dataObject.name = name;
}

很难在同一个类中维护所有这 45 个动作方法。有没有办法将这些方法写在单独的 ts 文件中并将它们导入到当前文件中?

编辑:添加 dataObject 接口的一部分以及它的一些操作方法

interface IDataObject{
    name:string;
    dataType:string;
    value:any;
    valueType:VALUE_TYPE|any;
    hasCustomValueType:boolean;
    customValueType:string|undefined;
    description:string;
    isRegistered:boolean;
    associatedVariableDetails:IVariableDetails[];
    hasMultipleValues:boolean;
    associatedService:SERVICE;
}

enum VALUE_TYPE{
    MAJOR = 'major',
    MED = 'med',
    MINOR = 'minor'
}

enum SERVICE{
    PUSH_IN = 'pushin',
    PULL_OUT = 'pullout'
}

interface IVariableDetails{
    variableName:string;
    varirbleDataType:string;
    variableValue:any;
    hasArray:boolean;
    isDeletable:boolean;    
}

//////////////
method to update dataType
@action updateDataType = (dataType:string) =>{
    this.dataObject.dataType = dataType;
    if(dataType === 'string'){
        this.dataObject.value = ''
    }
    else if(dataType === 'boolean'){
        this.dataObject.value = false
    }
    else if(dataType === 'integer'){
        this.dataObject.value = 0
    }
}


methods to modify associatedVariableDetails

@action addVariableDetails = (variableDetails:IVariableDetails) =>{
    this.dataObject.associatedVariableDetails.push(variableDetails);
}

@action updateMultipleValueState = (hasMultipleValues:boolean) =>{
    this.dataObject.hasMultipleValues = hasMultipleValues;
    if(!hasMultipleValues){
        this.dataObject.associatedVariableDetails = this.dataObject.associatedVariableDetails[0];
    }
}

标签: reactjstypescriptmobxmobx-react

解决方案


为您想要作为可观察对象的对象创建一个接口并添加索引签名。

这看起来像这样:

interface foo {
  [key: string]: type;
  bar: string;
}

然后将密钥传递给您的更新操作并更新值,例如object[key] = newValue.

例子:

    @action update = (key: string, value: type) => {
      object[key] = value;
    }

这将允许您使用一个函数将任何值修补到您的可观察对象中。

这是一篇深入解释索引签名的好文章:https ://basarat.gitbooks.io/typescript/docs/types/index-signatures.html

不过要回答你原来的问题。您可以创建 45 个函数并将它们全部导出到一个对象中,然后将它们导入此文件,但是如果类型或字段发生更改,该解决方案可能会过于繁琐且维护起来很繁琐。如果此解决方案不起作用,我可以举一个例子。我上面解释的解决方案是处理对象补丁的更有效方法。

编辑:

对于延迟编辑我的答案,我深表歉意。我已经对您上面的代码进行了编辑,显示了我将对您拥有的这种对象采取的方法。这是编辑:

interface IDataObject{
    [key: string]: string | boolean | VALUE_TYPE | SERVICE | IVariableDetails[];
    name: string;
    dataType: string;
    value: any; // THIS SHOULD BE STRICTLY DEFINED
    valueType: VALUE_TYPE|any; // THIS SHOULD ALSO BE STRICTLY DEFINED
    hasCustomValueType: boolean;
    customValueType?: string;
    description: string;
    isRegistered:boolean;
    associatedVariableDetails: IVariableDetails[];
    hasMultipleValues: boolean;
    associatedService: SERVICE;
}

enum VALUE_TYPE{
    MAJOR = 'major',
    MED = 'med',
    MINOR = 'minor'
}

enum SERVICE{
    PUSH_IN = 'pushin',
    PULL_OUT = 'pullout'
}

interface IVariableDetails{
    variableName:string;
    varirbleDataType:string;
    variableValue:any;
    hasArray:boolean;
    isDeletable:boolean;    
}

@action updateField = (key: string, value: string | boolean | VALUE_TYPE | SERVICE) => {
    this.dataObject[key] = value;
}
@action addVariableDetails = (variableDetails: IVariableDetails) => {
    this.dataObject.associatedVariableDetails.push(variableDetails);
}
@action updateMultipleValueState = (hasMultipleValues: boolean) => {
    this.dataObject.hasMultipleValues = hasMultipleValues;
    if(!hasMultipleValues){
        this.dataObject.associatedVariableDetails = this.dataObject.associatedVariableDetails[0];
    }
}

我在这里所做的是公开了一种操作半原始值的方法,之后不需要额外的工作,它们只需要新值。然后,我将@actions根据您需要对对象执行的工作类型根据需要创建更复杂的内容。如图所示,该updateField操作不允许您将其与某种VariableDetails类型的参数一起使用,如果您尝试将 variableDetails 参数发送到该操作,则打字稿会抱怨。

我还注意到,any如果对象的其余部分具有严格的类型,则属性肯定应该是某种类型。如果您要any在对象中包含类型,则不妨制作一个类似的接口interface IAny { [key: string]: any; }并在任何地方使用它。

我希望这能有所帮助,我再次为回复中的差距道歉。


推荐阅读