如何在单独的文件中编写mobx操作方法并将其导入具有可观察变量的实际mobx类?

时间:2019-04-05 06:32:38

标签: reactjs typescript mobx mobx-react

我有一个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];
    }
}

1 个答案:

答案 0 :(得分:0)

为所需的对象创建一个可观察的接口,并添加索引签名。

这看起来像这样:

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; }之类的接口,并在各处使用它。

我希望这会有所帮助,我再次为回应中的空白表示歉意。