Angular 2中DOM操作应该放在哪里?

17
在Angular 1中,所有的DOM操作都应该在指令中完成,以确保正确的可测试性,但是在Angular 2中有何变化呢?
我一直在搜索关于在哪里放置DOM操作以及如何进行操作时的思考方式的好文章或任何信息,但每次都找不到。
以这个组件为例(实际上这是一个指令,但让我们假装它不是):
export class MyComponent {

  constructor(private _elementRef: ElementRef) {

    this.setHeight();

    window.addEventListener('resize', (e) => {
      this.setHeight();
    });
  }

  setHeight() {
    this._elementRef.nativeElement.style.height = this.getHeight() + 'px';
  }

  getHeight() {
    return window.innerHeight;
  }
}

事件绑定应该放在构造函数中吗?还是应该放在ngAfterViewInit函数或其他地方?是否应该将组件的DOM操作拆分成指令?

目前一切都很模糊,所以我不确定自己是否做得正确,我相信我不是唯一一个有这种困惑的人。

Angular2中对DOM操作的规则是什么?

2个回答

16

开发者根据推荐的解决方案得出: http://angularjs.blogspot.de/2016/04/5-rookie-mistakes-to-avoid-with-angular.html

@Component({
  selector: 'my-comp',
  template: `
    <div #myContainer>
    </div>
  `
})
export class MyComp implements AfterViewInit {
  @ViewChild('myContainer') container: ElementRef;

  constructor() {}

  ngAfterViewInit() {
    var container = this.container.nativeElement;
    console.log(container.width); // or whatever
  }
}

注意:ViewChild的名称必须以myName开头,并且在模板中需要使用#。


2
不要忘记添加适当的导入:import { AfterViewInit, ViewChild } from '@angular/core'; 代码片段来自:https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#parent-to-view-child - JK Dennis
1
你还需要在代码中引入 import { ElementRef } from '@angular/core'; - Brian Riley
1
你是说名称中必须包含前缀 my 吗?还是指我们在 @ViewChild('whatever') 中引用的名称必须对应于模板标记中的 #whatever - Konrad Viltersten
@KonradViltersten 或许对你来说已经不再相关,但对其他人来说可能仍然有用;“my”前缀在名称中不一定必须存在,只需要相同即可,但强烈建议使用个人/自定义前缀,以免与其他模块产生冲突。 - Nathan

12

在Angular2中应避免直接操作DOM。

而是使用绑定,例如:

export class MyComponent {
  constructor() {
    this.setHeight();
  }

  @HostBinding('style.height.px')
  height:number;

  @HostListener('window:resize', ['$event'])
  setHeight() {
    this.height = window.innerHeight;
  }
}

1
你能详细说明一下吗? - Chrillewoodz
2
直接操作DOM不兼容于服务器端渲染和利用Angular的WebWorkers支持。 - Günter Zöchbauer
嗯,好的,我有点明白了,但是我不太理解这个 @HostBinding('style.height.px') height:number;height:number 部分是什么意思? - Chrillewoodz
抱歉,我漏掉了 window。我已经更新了我的答案。 - Günter Zöchbauer
刚在阅读Dart文档时找到了答案,哈哈。不管怎样还是谢谢你 :) 现在要重新写很多东西了...唉。 - Chrillewoodz
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接