angular2 检测 ng-content 的变化

Stw*_*sch 13 javascript angular

有没有办法检测 ng-content 的变化?

@Component({
    selector: 'example',
    template: `<ng-content></ng-content>`
})
export class Example {}

@Component({
    selector: 'test',
    template: `
        <example>
            <div *ngFor="let el of elements">{{el}}</div>
        </example>`
})
export class Test {
    elements = [1, 2, 3];

    ngOnInit() {
        setInterval(() => this.elements[0] += 10, 3000);
    }
}
Run Code Online (Sandbox Code Playgroud)

当我的 ng-content 发生变化时,我想在 Example 类中获取一些信息。

这里是plunker

Dyl*_*211 12

最简单的解决方案是使用cdkObserveContent指令。首先,您必须添加到拥有组件 ObserversModule 的模块的导入

import {ObserversModule} from '@angular/cdk/observers';

@NgModule({
  imports: [
    /* ...other modules you use... */
    ObserversModule
  ],

/* ... */
})
export class MyModule { }
Run Code Online (Sandbox Code Playgroud)

然后在您的组件模板中:

<div (cdkObserveContent)="onContentChange($event)">
  <ng-content></ng-content>
</div>
Run Code Online (Sandbox Code Playgroud)

每次内部内容发生某种变化时,该事件都会触发,传递给函数的值是一个数组,其中包含有关更改内容的所有详细信息。可以在 中找到已更改数据的值target.data

在你的 component.ts 中:

onContentChange(changes: MutationRecord[]) {
   // logs everything that changed
   changes.forEach(change => console.log(change.target.data));
}
Run Code Online (Sandbox Code Playgroud)

此外,您可以将其用作一项服务,为您提供 Observable<MutationRecord[]>

  • 我认为这是 2020 年最好的解决方案。`ngAfterContentChecked` 可能会触发太多次,这可能会损害性能。 (2认同)

Wil*_*ver 8

我的项目解决方案是监控内容的innerHTML。此示例来自显示模板内容的工具提示。我不太喜欢这个解决方案,很高兴提供不同/更好的解决方案。只要有变化,这就会发出。

/// tooltip.component.html
<div class="tooltip" [class.hidden]="hidden">
    <div #content>
        <ng-content></ng-content>
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)

 

///tooltip.component.js
import { AfterContentChecked, AfterContentInit, Component, ElementRef, EventEmitter, Output, ViewChild } from "@angular/core";

@Component({
    selector: "example",
    templateUrl: "./tooltip.component.html",
    styleUrls: ["./tooltip.component.scss"]
})
export class TooltipComponent implements AfterContentInit, AfterContentChecked {    
    @ViewChild("content") contentWrapper: ElementRef;
    content = "";
    @Output() public readonly contentChanged = new EventEmitter<string>();

    ngAfterContentInit(): void {
        this.content = this.contentWrapper.nativeElement.innerHTML;
        this.contentChanged.emit(this.content);
    }

    ngAfterContentChecked(): void {
        const c = this.contentWrapper.nativeElement.innerHTML;
        if (c !== this.content) {
            this.content = c;
            this.contentChanged.emit(this.content);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


bor*_*Blu 8

要检测ng-content假设您要添加的更改ItemComponent.

代码是:

import { QueryList, ContentChildren, AfterViewInit } from '@angular/core';

export class TestComponent implements AfterViewInit  {

    @ContentChildren(ItemComponent)
    public itemList:QueryList<ItemComponent>;


    public ngAfterViewInit() : void {
        this.itemList.changes.subscribe(() => {
            // put your logi here
        });
    }

}
Run Code Online (Sandbox Code Playgroud)

注意:
根据ContentChildren 文档,您必须等待ngAfterViewInit才能访问,QueryList因此无法在ngOnInit.

请参阅QueryList 文档以了解此类为您提供的所有其他属性。


Sim*_*ble -1

如果您尝试在每次绑定数据更新时完成某些操作,则可以使用ngOnChanges()生命周期挂钩。查看文档,了解更多信息。