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

18 浏览
0 Comments

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

在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操作有哪些规则?

0
0 Comments

Angular 2中应该尽量避免直接操作DOM。相反,应该使用绑定来实现,如下所示:

export class MyComponent {
  constructor() {
    this.setHeight();
  }
  ('style.height.px')
  height:number;
  ('window:resize', ['$event'])
  setHeight() {
    this.height = window.innerHeight;
  }
}

你能详细解释一下吗?

(...) 注册了一个事件监听器,(...) 更新了height样式的值为number的值。事件处理程序是错误的。我更新了我的答案(抱歉,在写这个答案的时候我只有手机)。

直接操作DOM与服务器端渲染和使用Angular的WebWorkers支持不兼容。

嗯,好吧,我有点理解了,但是我不太理解这一部分 ('style.height.px') height:number;height:number是做什么的?

这似乎表明监听器将监听宿主元素的调整大小,而不是窗口?

抱歉,我忽略了window。我更新了我的答案。

在阅读Dart文档时,我找到了答案,哈哈。不管怎样,谢谢 🙂 现在我需要大量重写代码了...唉。

这可能是正确的,在许多情况下,包括上面的情况,在模板中使用绑定已经足够。然而,有很多情况下,直接操作DOM是必要的,而模板是不够的。Angular 1通过link函数给了我们一个逃生通道。

我知道有些情况下这很困难或者不可能,但这是你应该努力的方向。我对Angular1了解不多。在Angular2中,你也可以操作DOM,但如果你想使用WebWorkers或服务器端渲染,这有它的缺点。你还可以使用ViewContainerRef.createComponent()在运行时动态添加/删除组件,甚至在运行时创建组件。

0
0 Comments

DOM操作在Angular 2中的位置是一个经常被讨论的问题。在开发者推荐的解决方案中,他们建议将DOM操作放在AfterViewInit生命周期钩子中进行。这样可以确保组件的视图已经初始化完成,可以安全地进行DOM操作。

以下是一个示例代码:

({
  selector: 'my-comp',
  template: `
    
` }) export class MyComp implements AfterViewInit { @ViewChild('myContainer') container: ElementRef; constructor() {} ngAfterViewInit() { var container = this.container.nativeElement; console.log(container.width); // or whatever } })

需要注意的是,视图子组件的名称必须以"my"开头,并且在模板中需要使用"#myContainer"来引用。同时,还需要添加适当的导入语句:

import { AfterViewInit, ViewChild, ElementRef } from '/core';

在讨论中,有人问到名称中是否必须包含前缀"my",或者是指在代码中引用的名称必须与模板中的"#whatever"对应。回答是名称中不必包含"my"前缀,只需要保持一致即可。不过,强烈建议在名称中使用个人/自定义前缀,以避免与其他模块冲突。

虽然这个问题可能对你来说已经不再重要,但对其他人来说可能仍然有参考价值。

0