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

Smo*_*son 10 javascript typescript angular

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

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

html

<button id="buy-now">BUY NOW</button>
Run Code Online (Sandbox Code Playgroud)

当你点击按钮时,我希望按钮变成紫色,所以在纯 javascript 中你会写一些类似的东西

javascript

changeColour() {
   const b = document.getElementById('buy-now');
   b.style.backgroundColor = 'purple';
}
Run Code Online (Sandbox Code Playgroud)

现在在 Angular 中我一直这样做,但最近注意到有人说这不正确?

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

任何帮助,将不胜感激!

编辑

明确地说,我知道在 Angular 中我可以做到这一点

HTML

<button (click)="changeColour()" id="buy-now">BUY NOW</button>
Run Code Online (Sandbox Code Playgroud)

文件

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

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

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

谢谢

Jah*_*wal 10

对文档美学的任何更改,如页面导航(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>
    
    Run Code Online (Sandbox Code Playgroud)

    TS

    buttonColor : string = 'grey'
    changeColour() {
        this.buttonColor = 'purple'
    }
    
    Run Code Online (Sandbox Code Playgroud)

    角也有一个功能,允许仅在执行事件侦听器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>
    
    Run Code Online (Sandbox Code Playgroud)

    所述colour按钮的变purpleCtrl+Shift+Enter被按下。

  2. @HostListener and @HostBinding

    这类似于event bindingproperty binding在角。

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

    并且与 @HostListener('click') click(){ }相同(click)="click()"

    @HostBindingand@HostListener在内部定义,directive[]()在 内部定义component template

    以下是我们示例的片段:

    HTML

    <button class="c_highlight">BUY NOW</button>
    
    Run Code Online (Sandbox Code Playgroud)

    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" ;
         }
     } 
    
    Run Code Online (Sandbox Code Playgroud)
  3. Renderer2

    这基本上是一个wrapperbrowser API for DOM Manipulation。Renderer2 API 可以across platforms在 DOM 之外运行,您可以提供own Renderer2 implementation平台独有的 . 有多个DOM操作methods本作同样喜欢setStyle()createElement()createText()appendChild()等,我们可以实现我们自己custom太方法。这类似于template reference variable您的示例中的 ,我们使用reference到元素到modify它的properties

    以下是我们示例的片段:

    HTML

    <button (click) = "onClick()" #abcd>BUY NOW</button>
    
    Run Code Online (Sandbox Code Playgroud)

    TS

    @ViewChild('abcd') 
    private abcd: ElementRef;   
    constructor(private renderer: Renderer2) {
    }
    onClick() {
        this.renderer.setStyle(this.abcd.nativeElement, 'backgroundColor','purple');
    }
    
    Run Code Online (Sandbox Code Playgroud)

    阅读更多 - https://angular.io/api/core/Renderer2

  4. Template Reference Variable

    这涉及id (reference)为元素创建一个。这类似于jquery其中每个元素都可以有一个id并且可以使用该getElementById()方法在这些元素上定义事件的方法。示例(如您的问题所示):

    HTML

    <button (click)="changeColour()" id="buy-now">BUY NOW</button>
    
    Run Code Online (Sandbox Code Playgroud)

    TS

    changeColour() {
        const b = <HTMLElement>document.querySelector('#buy-now');
        b.style.backgroundColour = 'purple'
    }
    
    Run Code Online (Sandbox Code Playgroud)
  5. fromEvent()fromrxjs:这类似于Event Listener在元素上定义 an 。该fromEvent方法创建一个Observable,它发出来自给定元素的特定类型的事件。只reference需要声明 for 元素;该事件是associated与此参考。例子:

    HTML

    <button #abcd>BUY NOW</button>
    
    Run Code Online (Sandbox Code Playgroud)

    TS

    @ViewChild('abcd') 
    private abcd: ElementRef;   
    ngOnInit(){
        fromEvent(this.abcd.nativeElement, 'click').subscribe(res => this.abcd.nativeElement.style.backgroundColor = 'purple');
    }
    
    Run Code Online (Sandbox Code Playgroud)

    总结

    所用技术的选择DOM Manipulation完全取决于developer. 这些方法中的每一个都有自己的benefitstrade-offs;像事件绑定一样,performance在修改大列表时可能会相对较慢,因为change detection cycle只有在此函数返回后才能再次运行。正如@Chellapan 所指出的,方法 1 和方法 2best angular practices与这些avoid creating references元素相同,这些元素可能有风险,并且会使您的应用程序更容易vulnerable受到XSS攻击。