Angular 2 - 单击时向DOM元素添加类

问题描述 投票:11回答:3

我试图添加一个类,它将其外观(例如汉堡到x)改为菜单触发器DOM元素,它有自己的方法来显示叠加菜单,但我无法弄清楚如何做到这一点。

这是我到目前为止 - 这是调用菜单本身的外部方法:

import { Component, ElementRef, ViewChild, Renderer, AfterViewInit } from '@angular/core';

import { LayoutService } from 'app/core/services/layout.service';

@Component({
    moduleId: module.id,
    selector: 'header-main',
    templateUrl: 'header-main.component.html',
})


export class HeaderMainComponent {

    @ViewChild('nav-trigger') el: ElementRef;

    constructor(private layoutService: LayoutService) { }

    menuToggle() {
        this.layoutService.mainMenuToggle();
        this.el.nativeElement.classList.add('opened');
    }
}

我是Angular 2的新手。这应该如何解决?我应该使用Renderer,为什么我应该使用Renderer?等问题


编辑:绝对点击事件(选择孩子,而不是父母)的问题是,我们必须使用与reference tag装饰器配对的@ViewChild,如下所示:

@ViewChild('navTrigger') navTrigger: ElementRef;,它与HTML模板中的#navTrigger引用有关。

因此:

export class HeaderMainComponent {
    logoAlt = 'We Craft beautiful websites'; // Logo alt and title texts

    @ViewChild('navTrigger') navTrigger: ElementRef;

    constructor(private layoutService: LayoutService, private renderer: Renderer) { }

    menuToggle(event: any) {
        this.layoutService.mainMenuToggle();
        this.renderer.setElementClass(this.navTrigger.nativeElement, 'opened', true);
    }
}
angular
3个回答
16
投票

要完成您想要的任务,您需要使用渲染器(使用private renderer: Renderer将其注入构造函数中)。 Renderer提供了对原生元素的抽象,并提供了与DOM交互的安全方式。

在您的模板中,您应该可以执行以下操作:

<div (click)="menuToggle($event)"></div>

这将捕获click事件并将其传递给menuToggle函数。

然后在您的组件中,您应该能够使用Renderer与DOM进行交互,如下所示:

menuToggle(event:any) {
    this.renderer.setElementClass(event.target,"opened",true);
}

根据setElementClassdocs的功能签名是setElementClass(renderElement: any, className: string, isAdd: boolean) : void

有关渲染器的进一步阅读,this is a good article on Medium。在讨论使用ViewChild并通过nativeElement访问DOM与使用Renderer相比时,它说:

这工作正常(使用ViewChild中的nativeElement)。我们在ViewChild装饰器的帮助下抓取input元素,然后访问本机DOM元素并在输入上调用focus()方法。

这种方法的问题在于,当我们直接访问本机元素时,我们放弃了Angular的DOM抽象,错过了在非DOM环境中执行的机会,例如:native mobile,native desktop,web worker或服务器端渲染。

请记住,Angular是一个平台,浏览器只是我们可以渲染我们的应用程序的一个选项。

希望这可以帮助。


6
投票

自Tyler回答以来,事情发生了一些变化。 Renderer折旧并由Renderer2取代。在Renderer 2,类setElementClassaddClass取代。根据addClass的说法,docs的新功能签名是

addClass(el: any, name: string): void

所以更新的menuToggle函数应该读取

menuToggle(event:any) {
    this.renderer.addClass(event.target,"opened");
}

0
投票

在组件中创建一个支持字段,然后绑定到ngClass并使用typescript表达式有条件地将该类添加到该元素。请注意,应使用单击事件来切换支持字段。例如。

  1. 在组件中:openedBool: boolean = false;
  2. toggleOpenedBool() { openedBool = !openedBool; }
  3. 在模板中:<div (click)="toggleOpenedBool()" [ngClass]="{'opened': openedBool}"></div>
© www.soinside.com 2019 - 2024. All rights reserved.