【问题标题】:Angular 2 - change neighbor input variable on input variable changeAngular 2 - 在输入变量更改时更改邻居输入变量
【发布时间】:2016-06-26 08:20:21
【问题描述】:

我想在更改输入参数时执行一些操作。假设我有一个 DatePicker 组件,它有一个 type 输入变量,并且我想在更改类型时对另一个 date 变量执行一些操作。该怎么做?

export class DatePicker {

    @Input()
    date: Date;

    @Output()
    dateChange = new EventEmitter();

    @Input()
    set type(type: string) {
        if (type === "today") {
            this.date = new Date();
            this.dateChange(this.date); // because of this change change detector will throw error
        }
    }

}

错误:检查后表达式已更改。

【问题讨论】:

  • 我建议你先做@Input() date: any;然后处理Input变量
  • this.dateChange(this.date); 应该是this.dateChange.emit(this.date);(缺少emit
  • 这里有一个应该避免的时间耦合。要求date 设置在type 之前。要么将两者合并到一个 date: Date | string 中,要么将它们放在一个对象中。甚至dateChange 也应该已经有一个监听器,听起来最好找到不同的方法。
  • 有很多用例是当输入改变时你必须做一些事情,比这个例子更不耦合。但是你不能做任何事情,这是一个问题。还有this与此问题相关的讨论

标签: typescript angular angular2-components angular2-inputs


【解决方案1】:

更新

当更改检测本身具有导致模型更改的副作用时,Angular2 会导致此错误,这通常表示导致 Angular2 应用程序工作效率低下的错误或设计缺陷。

隐藏此类问题,您只需启用prodMode

生命周期方法中模型更改的解决方法调用 ChangeDetectorRef.detectChanges() 以明确表明此模型更改是有意的

export class DatePicker {

    constructor(private cdRef:ChangeDetectorRef) {}

    @Input()
    date: Date;

    @Output()
    dateChange = new EventEmitter();

    @Input()
    set type(type: string) {
        if (type === "today") {
            this.date = new Date();
            this.dateChange(this.date); 
            this.cdRef.detectChanges();
        }
    }
}

原创

您可以使用setTimeout() setTimeout() 是一种大锤方法,因为它会导致整个应用程序的更改检测周期。

@Input()
set type(type: string) {
    if (type === "today") {
        this.date = new Date();
        setTimeout(() => this.dateChange(this.date)); 
    }
}

type 被更改检测更新时这是必要的,因为Angular2 不喜欢更改检测导致更改。

另一种方法是使用ngOnChanges(),但这也被更改检测调用,并且还需要setTimeout() Workaround

export class DatePicker implements OnChanges {

    @Input()
    date: Date;

    @Output()
    dateChange = new EventEmitter();

    @Input()
    set type:string;

    ngOnChanges(changes:SimpleChanges) {
      if(changes['type']) {
        if (type === "today") {
            this.date = new Date();
            setTimeout(() => this.dateChange(this.date));
        }
      }
    }
}

这两种方法的区别在于,第一种方法对每次更改都执行代码,最后一种仅针对由绑定引起的更改。

【讨论】:

  • 使用 setTimeout 看起来像猴子补丁。我们在 angular1 中使用 setTimeout 并应用相同的猴子补丁。我们需要更好的东西
  • 我听说过很多次关于setTimeout()。只要其他代码不依赖于通过或尚未通过的特定时间,我看不到setTimeout() 的问题。它所做的只是安排在当前更改检测周期完成后发生更改,并在更改后调用另一个更改检测。
  • 你可以尝试注入private cdRef:ChangeDetectorRef并在this.dateChange(this.date)之后调用this.cdRef.detectChanges()
  • 我认为这是我遇到此问题时尝试的第一个解决方案,现在不确定,需要检查,但我记得它也导致错误
  • setTimeout 不能解决同步任务。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-03
  • 2018-10-20
  • 1970-01-01
  • 1970-01-01
  • 2020-02-01
相关资源
最近更新 更多