子组件:TitleComponent

title.component.ts

import { Component, EventEmitter, Input, Output } from '@angular/core';

@Component({
    selector: 'app-title',
    template: `<h2>{{title}}</h2><br/>
    <ul *ngFor="let message of messages"><li>{{message}}</li></ul><br/>
    <button (click)="click()">确定</button>  
    <button (click)="update()">值变更</button>
    `
})
export class TitleComponent {
    @Input() title = '';
    @Input() messages: string[] = [];
    @Output() output: EventEmitter<any> = new EventEmitter();
    constructor() { }

    click(): void {
        this.output.emit();
    }

    update(): void {
        this.title = 'hello';
        this.messages = [];
    }
}

父组件:Tab1Page

tab1.page.html

<app-title (output)="output()" [title]="title" [messages]="messages"></app-title>

tab1.page.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-tab1',
  templateUrl: 'tab1.page.html',
  styleUrls: ['tab1.page.scss']
})
export class Tab1Page {
  title:string = '';
  messages:string[] = [];

  constructor() {}

  public output(): void {
    this.title = 'world';
    this.messages.push('how are you');
  }
}

Angular 无法触发子组件@Input()值变化的奇怪问题_ngOnChange

点击确定按钮

Angular 无法触发子组件@Input()值变化的奇怪问题_变化检测_02

再次点击

Angular 无法触发子组件@Input()值变化的奇怪问题_html_03

好了没问题,现在点击值变更按钮

Angular 无法触发子组件@Input()值变化的奇怪问题_html_04

然后再点击确定按钮,发现不管点击多少次都是下面这个样子

Angular 无法触发子组件@Input()值变化的奇怪问题_html_05

很奇怪吧。现在我们修改下tab1.page.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-tab1',
  templateUrl: 'tab1.page.html',
  styleUrls: ['tab1.page.scss']
})
export class Tab1Page {
  title:string = '';
  messages:string[] = [];
  int: number = 1;

  constructor() {}

  public output(): void {
    this.int++;
    this.title = 'world ' + this.int;
    const messages = [];
    messages.push('how are you');
    this.messages = messages;
  }
}

重新执行上面的操作,值变更后点确定

Angular 无法触发子组件@Input()值变化的奇怪问题_html_06

Angular 无法触发子组件@Input()值变化的奇怪问题_html_07

会一直有值,这是为什么呢?我个人猜测是第一次的时候没有触发angular的赃检测,而第二次因为两个变量的值改变并且内存地址也改变所以触发的赃检测。

遇到这种解决办法:

一、使用@ViewChild

<app-title #apptitle (output)="output()" [title]="title" [messages]="messages"></app-title>

import { Component, ViewChild } from '@angular/core';
import { TitleComponent } from '../title/title.component';

@Component({
  selector: 'app-tab1',
  templateUrl: 'tab1.page.html',
  styleUrls: ['tab1.page.scss']
})
export class Tab1Page {
  @ViewChild('apptitle') apptitle: TitleComponent;
  title:string = '';
  messages:string[] = [];

  constructor() {}

  public output(): void {
    this.apptitle.title = 'world';
    this.apptitle.messages.push('how are you');
  }
}

二、对于数组有两种办法

1)清空值的时候不要用this.messages = [];这种重新赋值的方式,用下面方式清空数组

this.messages.splice(0);

2)在赋值的时候采用es6的写法

this.messages= [...this.messages, 'how are you'];