子模型 getter 和 setter 不能在 angular 2/4 中工作

Posted

技术标签:

【中文标题】子模型 getter 和 setter 不能在 angular 2/4 中工作【英文标题】:Child model getter and setter are not working in angular 2/4 【发布时间】:2018-05-03 11:25:22 【问题描述】:

我有一种情况,我定义了三个模型类,如下所示

export class Parent 

    name: string;
    containers: Container[];  


export class Container

    desc: string;
    sets: Sets[];  



export class Sets

    private _data?: any[];
    private _dataSet?: any[];

    get data() 
    
        if (this.dataSet && this.dataSet.length > 0) 
        
            return this._dataSet[0].data;
        
        return this._data;
    

    set data(data: any[]) 
    
        this._data = data;
    

    get dataSet() 
    
        return this._dataSet;
    

    set dataSet(dataSet: any[]) 
    
        this._dataSet = dataSet;
    

问题是:Set 类的gettersetter 方法不会被触发,除非我明确执行new Set()(我不知道new Set() 是否真的有必要)。

例如:

"name": "vik",
"containers": [

    "desc": "something",
    "sets": [
    
        "dataSet": [
        
            "data":[
            
                // Object
            ]
        ]
    ]
]

当我这样做时:

let response:Parent = responseObj;
console.log(response.containers[0].sets[0].data)

它应该返回数据集value,但它却返回undefined

但如果我这样做:

let response:Parent = responseObj;
console.log(new Sets(response.containers[0].sets[0]).data)

返回正确的值。

我是否遗漏了什么或如何改进我的代码以使其正常工作?

【问题讨论】:

对于多重嵌套,您可以做的不多。见this answer。 你的对象是不是来自外部,比如http响应? 是的,这是一个http响应 那我给你一个答案,但你不会喜欢它( 让响应:Parent = JSON.parse(responseOb)j; console.log(response.containers[0].sets[0].data) 试过了吗? 【参考方案1】:

问题是您的对象来自 HTTP。这是什么意思:

Http 是一种基于文本的格式。这意味着当您收到响应时,它是唯一的字符串,例如:

""foo":"boor""

然后你像 JSON.parse(data) 一样做 smth 并返回像这样的真实对象:

foo: "bar";

但 JSON.parse 对您所期望的 type 没有任何作用。它不知道如何从对象的字符串实例中生成。它可以尝试制作一个简单的对象,仅此而已。

你看,你的数据对象没有关于它的类型、方法、getter/setter 等的信息。它只是关于平面数据,也就是 dto。所以,如果你想从你的 dto 中获取真正的类,你应该编写更智能的解析器,它将获取你的 dto 并从中创建预期类的真实实例。 基本上你已经这样做了

new Sets(response.containers[0].sets[0])

因此您可以继续这样做,但您会发现这些重复代码遍布您的应用程序。我发现最好的方法是将映射器注入数据服务器并返回不是 dto 而是一个实例。因此,您的其他代码不会对这种“脏”工作一无所知,并且将始终与“正常”对象一起工作。

希望这会有所帮助。

更新:

const rawData = '"name":"Vitalii"';
const person1 = JSON.parse(rawData);

function Person(name) 
  this.name = name;
  this.say = function() 
    console.log(`Hi, $this.name`);
  


let person2 = new Person(person1);
person2.say();

// person1 and person2 have the same data inside. But: 

console.log(person2 instanceof Person); // true
console.log(person1 instanceof Person); // false

这是因为即使看起来相似,这个对象也有不同的性质。

【讨论】:

但是当我这样做时它不应该工作吗,新父母(响应)?? 这取决于您将在构造函数中放入什么逻辑。从您的回复中,您只能获得数据,仅此而已。然后,您必须为树中具有方法的每个对象创建新对象。 :( 抱歉,我没有看到任何东西可以代替你或我来完成这项工作。 你应该明白,在你的类和你从 JSON.parse 或其他类似的东西得到的原始数据之间有一个巨大而深刻的整体。 所以为了明确一点,如果我有一个内部有自定义类型的对象,那么每个自定义类型都必须用 new 关键字实例化才能运行 setter 和 getter ...我是对还是我理解错了? 如果你的班级里除了字段(getter、setter、静态字段、函数)之外还有其他东西——是的。我将添加一个小例子,这可能会使我的解释更清楚。【参考方案2】:

是的,您必须(以某种方式)将您的普通对象解析为您定义的类实例,其他人已经为您回答了。

所以我只建议一种重构方式:nested object of class transformer

import  Type, plainToClass  from 'class-transformer';

export class Parent 
    @Type(() => Container)
    name: string;
    containers: Container[] = [];  
    static fromJson(json: any): Parent 
      return plainToClass<any, Parent>(Parent, json);
    


export class Container
    @Type(() => Set)
    desc: string;
    sets: Set[] = [];


export class Set
    private _data?: any[];
    private _dataSet?: any[];

    //your code

然后

let response:Parent = responseObj;
console.log(Parent.fromJson(response).containers[0].sets[0].data)

我觉得这样更整洁

希望对你有所帮助~

【讨论】:

以上是关于子模型 getter 和 setter 不能在 angular 2/4 中工作的主要内容,如果未能解决你的问题,请参考以下文章

覆盖 ExtJS 模型 getter 和 setter 的最佳实践

Angular 2使用getter和setter将输入表单值与模型绑定

为啥我不能将自动实现的 getter 和 setter 与 List 一起使用? (统一,C#)

getter 和 setter方法

Flutter 中的 Getter/Setter 使用 Android Studio

setter 和 getter 的模板