我有一个指令负责我页面上的汉堡菜单,它看起来像这样:
@Directive({
selector: '[sideNavToggler]'
})
export class SidenavtogglerDirective implements AfterViewInit {
private sideNav: HTMLElement
private burgerButton: HTMLElement
constructor(private el: ElementRef, private renderer: Renderer2) { }
ngAfterViewInit(): void {
this.sideNav = this.el.nativeElement.querySelector('.menu__box')
this.burgerButton = this.el.nativeElement.querySelector('.menu__btn')
}
@HostListener('click') toggleOpenClass(){
if (this.sideNav && this.burgerButton) {
this.sideNav.classList.contains('open')
? this.renderer.removeClass(this.sideNav,'open')
: this.renderer.addClass(this.sideNav, 'open')
this.burgerButton.classList.contains('active')
? this.renderer.removeClass(this.burgerButton,'active')
: this.renderer.addClass(this.burgerButton,'active')
}
}
}
它工作得很好,但我不认为使用 .querySelector 是 Angular 应用程序中的最佳实践。我在互联网上没有找到任何与我的情况类似的有用信息。我怎样才能使这段代码变得更好或者它已经足够了?我正在使用 Angular 16
使用指令时需要使用
ContentChild
,请在下面找到一个工作示例供您参考。
CSS
.active {
background-color: red;
}
.open {
background-color: yellow;
}
.hamburger-menu {
border: 1px solid black;
}
main.ts
import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';
import { SidenavtogglerDirective } from './side-nav-toggler.directive';
@Component({
selector: 'app-root',
standalone: true,
imports: [SidenavtogglerDirective],
template: `
<div class="hamburger-menu" sideNavToggler>
click inside to change color<br/>
<label class="menu__btn active" for="menu__toggle" #menuButton>
<span>label</span>
</label>
<ul class="menu__box open" #menuBox>
<li><a class="menu__item" href="#">hello</a></li>
</ul>
</div>
`,
})
export class App {
name = 'Angular';
}
bootstrapApplication(App);
指令
import {
Directive,
HostListener,
Renderer2,
AfterViewInit,
ViewChild,
ElementRef,
ContentChild,
} from '@angular/core';
@Directive({
selector: '[sideNavToggler]',
standalone: true,
})
export class SidenavtogglerDirective implements AfterViewInit {
@ContentChild('menuBox') menuBox!: ElementRef<HTMLElement>;
@ContentChild('menuButton') menuButton!: ElementRef<HTMLElement>;
constructor(private renderer: Renderer2) {}
ngAfterViewInit(): void {}
@HostListener('click', ['$event.target'])
toggleOpenClass() {
if (this.menuBox && this.menuButton) {
console.log(this.menuBox.nativeElement.classList.contains('open'));
this.menuBox.nativeElement.classList.contains('open')
? this.renderer.removeClass(this.menuBox.nativeElement, 'open')
: this.renderer.addClass(this.menuBox.nativeElement, 'open');
this.menuButton.nativeElement.classList.contains('active')
? this.renderer.removeClass(this.menuButton.nativeElement, 'active')
: this.renderer.addClass(this.menuButton.nativeElement, 'active');
}
}
}