Angular - '倾听'在@ViewChild上更改

时间:2018-05-16 15:47:03

标签: angular

如何实现像onElChanged这样的函数,以便每次<div #plot id="plot-container"></div>的属性发生变化时都会执行此函数?

component.html

<div #plot id="plot-container"></div>

component.ts

@ViewChild('plot') el: ElementRef;

onElChanged(){
  console.log(this.el.nativeElement.clientWidth);
}

3 个答案:

答案 0 :(得分:1)

我知道,没有办法监听元素的属性更改(对于这种情况)。虽然可能有一些其他库可以实现这一目标。这可能会有所帮助:

this.el.nativeElement.addEventListener(typeOfEvent);

答案 1 :(得分:1)

您可以创建一个指令,使用MutationObserver来侦听DOM中特定元素的属性更改。

<强> DOM-change.directive.ts

import { Directive, ElementRef, EventEmitter, OnDestroy, Output } from '@angular/core';

@Directive({
  selector: '[domChange]'
})
export class DomChangeDirective implements OnDestroy {
  private changes: MutationObserver;

  @Output()
  public domChange = new EventEmitter();

  constructor(private elementRef: ElementRef) {
    const element = this.elementRef.nativeElement;

    this.changes = new MutationObserver((mutations: MutationRecord[]) => {
        mutations.forEach((mutation: MutationRecord) => this.domChange.emit(mutation));
      }
    );

    this.changes.observe(element, {
      attributes: true
    });
  }

  ngOnDestroy(): void {
    this.changes.disconnect();
  }
}

<强> component.html

<div id="plot-container" (domChange)="onDomChange($event)"></div>

<强> component.ts

onDomChange($event: Event): void {
    console.log($event);
  }

答案 2 :(得分:0)

虽然不是使用@ViewChild装饰器的解决方案,但尽管您观察到的特定主题是非列表式的单数元素,但您仍可以使用非常相似的@ViewChildren装饰器来订阅更改

您可以使用first(或lastQueryList成员来获取ElementRef值-忽略{{1}的大多数列表特定部分}介面-这是我在下面使用的快速而肮脏的方法。 但是,建议您迭代处理一个长度为1的单数元素,以遵循典型的QueryList范式并创建更通用的方法和服务。

@ViewChildren

或来自组件外部存在的侦听器的示例(出于特殊考虑,通过@ViewChildren('plot', {read: ElementRef}) el: QueryList<ElementRef>; /** * Listen within this component */ private listenForPlotChanges() { this.el.changes.subscribe( (next: QuerList<ElementRef>) => { console.log('listenForPlotChanges next:', next); const plot = next.first.nativeElement; console.log('listentForPlotChanges plot:', plot); } ); } 说明了对元素的更新)...

Renderer2

我在Angular版本import { ElementRef, Injectable, QueryList, Renderer2, RendererFactory2 } from '@angular/core'; import { ISubscription } from 'rxjs/Subscription'; /** * Listen and update with renderer as a service outside a component * * Usage: * @ViewChildren('yourElement', {read: ElementRef}) el: QueryList<ElementRef>; * * constructor(listener: ListenerService) {} * * ngAfterViewInit() { * this.listener.listenForPlotChanges(this.el); * } */ @Injectable() export class ListenerService { private renderer: Renderer2; constructor(rendererFactory: RendererFactory2) { this.renderer = rendererFactory.createRenderer(null, null); } listenForPlotChanges(elementQueryList: QueryList<ElementRef>): ISubscription { const resolveNext = (next) => { console.log('listenForPlotChanges next:', next); const plot = next.first.nativeElement; console.log('listentForPlotChanges plot:', plot); this.renderer.addClass(plot, 'twist'); } return elementQueryList.changes.subscribe( (next: QueryList<ElementRef>) => { resolveNext(next); } } } 中使用了建议的方法,但尚未对其他Angular版本(包括最新版本)进行验证。