每次模型在角度2变化时如何调用函数?

时间:2016-03-28 12:43:20

标签: angular

我有一个自定义选择组件,当你点击li项目时会设置模型,但由于我每次更改模型时都会手动调用this.modelChange.next(this.model),因此我非常混乱和可重复我想避免。

所以我的问题是,是否有类似$scope.$watch的内容,我可以观察值是否发生变化,然后每次发生时调用this.modelChange.next(this.model)

我一直在阅读有关Observables但我无法弄清楚如何将其用于一个简单的值,因为我看到的所有示例都是对外部api:s的异步请求。

当然必须有一种更简单的方法来实现这一目标?

(不是我不能使用ngModelChanges,因为我实际上并没有使用输入。)

import {Component, Input, Output, EventEmitter, OnInit, OnChanges} from 'angular2/core';

@Component({
  selector: 'form-select',
  templateUrl: './app/assets/scripts/modules/form-controls/form-select/form-select.component.html',
  styleUrls: ['./app/assets/scripts/modules/form-controls/form-select/form-select.component.css'],
  inputs: [
    'options',
    'callback',
    'model',
    'label'
  ]
})

export class FormSelectComponent implements OnInit, OnChanges {
  @Input() model: any;
  @Output() modelChange: EventEmitter = new EventEmitter();

  public isOpen: boolean = false;

  ngOnInit() {

    if (!this.model) {
      this.model = {};
    }

    for (var option of this.options) {

      if (option.model == (this.model.model || this.model)) {
        this.model = option;

      }
    }
  }

  ngOnChanges(changes: {[model: any]: SimpleChange}) {
    console.log(changes);
    this.modelChange.next(changes['model'].currentValue);
  }

  toggle() {
    this.isOpen = !this.isOpen;
  }

  close() {
    this.isOpen = false;
  }

  select(option, callback) {
    this.model = option;
    this.close();

    callback ? callback() : false;
  }

  isSelected(option) {
    return option.model === this.model.model;
  }
}

编辑:我尝试使用ngOnChanges(请参阅上面的更新代码),但它只在初始化时运行一次,然后才检测到更改。有什么不对吗?

4 个答案:

答案 0 :(得分:20)

  

所以我的问题是,是否有类似于$ scope的内容。$ watch我可以观察输入属性model的值是否发生变化

如果model是JavaScript基元类型(Number,String,Boolean),那么您可以实现ngOnChanges()以通知更改。请参阅cookbook examplelifecycle doc, OnChanges section 另一种选择是使用setter和getter。请参阅cookbook example

如果model是JavaScript引用类型(数组,对象,日期等),那么检测更改的方式取决于模型的更改方式:

  • 如果模型引用发生更改(即,您分配了新数组或新对象等),则可以实现ngOnChanges()以获得更改通知,就像原始类型一样。
  • 但是,如果模型引用未更改,但模型的某些属性更改(例如,数组项的值更改,或添加或删除数组项,或者对象属性值更改),您可以实现ngDoCheck()来实现自己的更改检测逻辑。
    请参阅lifecycle doc, DoCheck section

答案 1 :(得分:3)

如果您选择内部使用表单输入的自定义组件,我会利用它上面的ngModelChange事件:

<select [ngModel]="..." (ngModelUpdate)="triggerUpdate($event)">…</select>

或valueChanges可观察相应的控件(如果有)。在模板中:

<select [ngFormControl]="myForm.controls.selectCtrl">…</select>

在组件中:

myForm.controls.selectCtrl.valueChanges.subscribe(newValue => {
  (...)
});

答案 2 :(得分:1)

ngAfterViewChecked是一个更好的生命周期方法,因为它在渲染DOM之后被调用,并且可以在此处完成任何操作。

https://stackoverflow.com/a/35493028/6522875

答案 3 :(得分:0)

您可以通过添加model方法使ngOnChanges(changes) {}成为getter / setter或实现OnChanges,每次@Input()值更改后调用该方法。

文档中的ngOnChanges()示例(上面链接):

@Component({
  selector: 'my-cmp',
  template: `<p>myProp = {{myProp}}</p>`
})
class MyComponent implements OnChanges {
  @Input() myProp: any;
  ngOnChanges(changes: {[propName: string]: SimpleChange}) {
    console.log('ngOnChanges - myProp = ' + changes['myProp'].currentValue);
  }
}
@Component({
  selector: 'app',
  template: `
    <button (click)="value = value + 1">Change MyComponent</button>
    <my-cmp [my-prop]="value"></my-cmp>`,
  directives: [MyComponent]
})
export class App {
  value = 0;
}
bootstrap(App).catch(err => console.error(err));

<强>更新

如果model的内部状态发生变化但model本身(不同的model实例)发生变化,则更改检测无法识别它。您需要实现自己的机制来通知感兴趣的代码,例如在Observable中使用model发出组件可以订阅的更改事件。

ngOnChanges()仅在数据绑定更改model时调用(someFieldInParent<my-comp [model]="someFieldInParent">中更改且Angular将新值传递给model时} MyComponent

return option.model === this.model.model;不会导致ngOnChanges()被调用。为此,getter / setter方法更适合。