Angular2子属性更改未在绑定属性上触发更新

Dyn*_*nde 15 typescript angular

我有一个带有输入的简单自定义指令,我在我的组件中绑定.但无论出于何种原因,更改输入属性的子属性时都不会触发ngOnchanges()方法.

my.component.ts

import {Component} from 'angular2/core';
import {MyDirective} from './my.directive';

@Component({
    directives: [MyDirective],
    selector: 'my-component', 
    templateUrl: 'Template.html'
})

export class MyComponent {
    test: { one: string; } = { one: "1" }

    constructor( ) {
        this.test.one = "2";
    }
    clicked() {
        console.log("clicked");
        var test2: { one: string; } = { one :"3" };
        this.test = test2; // THIS WORKS - because I'm changing the entire object
        this.test.one = "4"; //THIS DOES NOT WORK - ngOnChanges is NOT fired=
    }
}
Run Code Online (Sandbox Code Playgroud)

my.directive.ts

import {Directive, Input} from 'angular2/core';
import {OnChanges} from 'angular2/core';

@Directive({
    selector: '[my-directive]',
    inputs: ['test']
})

export class MyDirective implements OnChanges {
    test: { one: string; } = { one: "" }

    constructor() { }

    ngOnChanges(value) {
        console.log(value);
    }
}
Run Code Online (Sandbox Code Playgroud)

template.html

<div (click)="clicked()"> Click to change </div>
<div my-directive [(test)]="test">
Run Code Online (Sandbox Code Playgroud)

谁能告诉我为什么?

Thi*_*ier 14

事实上,这是一种正常的行为,Angular2不支持深度比较.它仅基于参考比较.请参阅此问题:https://github.com/angular/angular/issues/6458.

这表示他们是一些解决方法,通知指令对象中的某些字段已更新.

  • 引用组件中的指令

    export class AppComponent {
      test: { one: string; } = { one: '1' }
      @ViewChild(MyDirective) viewChild:MyDirective;
    
      clicked() {
        this.test.one = '4';
        this.viewChild.testChanged(this.test);
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    在这种情况下,显式调用指令的testChanged方法.请参阅此plunkr:https://plnkr.co/edit/TvibzkWUKNxH6uGkL6mJ p = preview .

  • 使用服务中的事件

    专用服务定义testChanged事件

    export class ChangeService {
      testChanged: EventEmitter;
    
      constructor() {
        this.testChanged = new EventEmitter();
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    该组件使用服务来触发testChanged事件:

    export class AppComponent {
      constructor(service:ChangeService) {
        this.service = service;
      }
    
      clicked() {
        this.test.one = '4';
        this.service.testChanged.emit(this.test);
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    该指令订阅此testChanged事件以便得到通知

    export class MyDirective implements OnChanges,OnInit {
      @Input()
      test: { one: string; } = { one: "" }
    
      constructor(service:ChangeService) {
        service.testChanged.subscribe(data => {
          console.log('test object updated!');
        });
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)

希望它对你有帮助,蒂埃里

  • 我明白了...嗯,那令人失望.老实说,我认为应该可以决定你是否需要进行深度比较.如果几乎所有其他js框架都支持它,性能就不会那么糟糕. (2认同)