在Angular 2+中进行DOM操作的正确方法

时间:2019-01-29 03:09:10

标签: javascript angular typescript

我知道有一些类似的问题,但没有一个回答我的问题。

基本上,什么是正确的操作DOM的正确方法,说我有这个。

html

<button id="buy-now">BUY NOW</button>

,当您单击按钮时,我希望按钮变为紫色,因此在纯JavaScript中,您会编写类似

javascript

changeColour() {
   const b = document.getElementById('buy-now');
   b.style.backgroundColor = 'purple';
}

现在在Angular中,我一直采用这种方式,但是最近发现有人说这是不正确的?

按角度操作DOM的正确方法是什么,我将如何重写示例以反映此更正的方法?

任何帮助将不胜感激!

编辑

要清楚,我知道在Angular中我可以做到

HTML

<button (click)="changeColour()" id="buy-now">BUY NOW</button>

TS文件

changeColour() {
   const b = <HTMLElement>document.querySelector('#buy-now');
   b.style.backgroundColour = 'purple'
}

但这是操纵dom的合适方法吗?

更改按钮颜色只是一个简单的例子,对于任何类型的DOM操作而言,我的意思都是

谢谢

3 个答案:

答案 0 :(得分:4)

对文档美学的任何更改,例如页面导航(routing),项目选择(ngIf),循环迭代(ngFor)等,都是DOM Manipulation。它可以由property驱动,也可以由event触发或reference处理。

Angular提供了多种处理DOM Manipulation的方法。

  1. EVENT BINDING

    从组件中的elements到相应组件的class的信息流是事件绑定(HTML Template to TS)。事件绑定的工作无需定义template reference variable.,这是操作DOM元素的最佳和最简便的方法。 ()表示event binding

    下面是本示例的代码段:

    HTML

    <button (click)="changeColour()" [ngStyle]="{'background-color': buttonColor}">BUY NOW</button>
    

    TS

    buttonColor : string = 'grey'
    changeColour() {
        this.buttonColor = 'purple'
    }
    

    Angular还具有仅在particular event上实现事件侦听器的功能,例如,在enter key is pressedmouse clickedcombination of keys is pressed上实现。

    下面是本示例的代码段:

    HTML

    <button (keyup.control.shift.enter)="changeColour()" [ngStyle]="{'background-color': buttonColor}">BUY NOW</button>
    

    当按下colour时,按钮的purple变成Ctrl+Shift+Enter

  2. @HostListener and @HostBinding

    这与event bindingproperty binding的角度相似。

    @HostBinding('value') val;[value]="val"

    @HostListener('click') click(){ }(click)="click()"相同。

    @HostBinding@HostListenerdirective内部定义,而[]()component template内部定义。

    下面是本示例的代码段:

    HTML

    <button class="c_highlight">BUY NOW</button>
    

    TS (host.directive.ts)

    @Directive({
        // Notice the . in selector => this directive will work for DOM with the c_highlight class 
        selector: '.c_highlight'
     })
    
     export class HostDirective {
    
         @HostBinding('style.backgroundColor') c_color = "red"; 
    
         @HostListener('click') c_onclick() {
             this.c_color = "purple" ;
         }
     } 
    
  3. Renderer2

    这基本上是wrapper上方的browser API for DOM Manipulation。除了DOM之外,还可以运行across platforms来运行Renderer2 API,并且可以提供平台独有的own Renderer2 implementation。目前存在多种DOM操作methods,例如setStyle()createElement()createText()appendChild()等,我们可以实现自己的{{1} }方法。这与您的示例中的custom类似,我们在元素template reference variable的{​​{1}}中使用reference

    下面是本示例的代码段:

    HTML

    modify

    TS

    properties

    了解更多-https://angular.io/api/core/Renderer2

  4. <button (click) = "onClick()" #abcd>BUY NOW</button>

    这涉及为元素创建@ViewChild('abcd') private abcd: ElementRef; constructor(private renderer: Renderer2) { } onClick() { this.renderer.setStyle(this.abcd.nativeElement, 'backgroundColor','purple'); } 。这类似于Template Reference Variable方法,其中每个元素可以具有一个id (reference),并且可以使用jquery方法在这些元素上定义事件。示例(如您的问题所示):

    HTML

    id

    TS

    getElementById()
  5. <button (click)="changeColour()" id="buy-now">BUY NOW</button> 来自changeColour() { const b = <HTMLElement>document.querySelector('#buy-now'); b.style.backgroundColour = 'purple' } : 这类似于在元素上定义fromEvent()rxjs方法创建一个Event Listener,它发出来自给定元素的特定类型的事件。只需要声明元素的fromEvent;该引用的事件为Observable。示例:

    HTML

    reference

    TS

    associated

    摘要

    用于<button #abcd>BUY NOW</button> 的技术的选择仅取决于@ViewChild('abcd') private abcd: ElementRef; ngOnInit(){ fromEvent(this.abcd.nativeElement, 'click').subscribe(res => this.abcd.nativeElement.style.backgroundColor = 'purple'); } 。这些方法中的每一个都有自己的DOM Manipulationdeveloper;就像事件绑定一样,benefits可能在修改大型列表时相对较慢,因为trade-offs仅在该函数返回后才能再次运行。方法1和2是performance,因为这些元素change detection cycle可能会带来风险,并且可能使您的应用程序受到{@Chellapan指出的best angular practices更多avoid creating references攻击。 / p>

答案 1 :(得分:2)

您可以使用template reference variable访问模板中的DOM元素:

<button #btn (click)="btn.style.backgroundColor = 'purple'">BUY NOW</button>

或者您可以将变量传递给方法:

<button #btn (click)="changeColor(btn)">BUY NOW</button>

并修改代码中的元素:

changeColour(element: HTMLElement) {
   element.style.backgroundColour = 'purple';
}

有关演示,请参见this stackblitz

答案 2 :(得分:2)

根据使用Element Ref的Angular文档可能容易受到攻击

  

允许直接访问DOM可以使您的应用程序更多   容易受到XSS攻击。仔细检查对ElementRef的任何使用   您的代码。有关更多详细信息,请参阅《安全指南》。

使用Renderer2来操作DOM。

在模板中创建一个模板引用,并将其传递给changeColour方法并使用renderer2服务,该服务提供setStyle方法来设置元素的样式

component.html

<button #button (click)="changeColour(button)">BUY NOW</button>

component.ts

constructor(private renderer: Renderer2) { }

changeColour(element: HTMLElement) {
  this.renderer.setStyle(element.nativeElement, 'backgroundColour ', 'purple');
}

参考:https://angular.io/api/core/ElementRef#security-risk