Angular中用TypeScript为Div添加CSS类:滚动时类未生效
问题解决:滚动时无法给Div添加CSS类
问题根源
this.el.nativeElement获取的是当前组件的宿主DOM元素,并非页面中目标.line元素,导致line.length为undefined,循环逻辑完全未执行- 即使宿主元素就是目标Div,单个DOM元素也没有
length属性,循环不会触发
修复方案
方案1:处理单个目标元素(推荐)
用@ViewChild直接绑定目标Div,精准获取元素:
import { Component, ElementRef, HostListener, ViewChild } from '@angular/core'; export class TestComponent { @ViewChild('targetLine') targetLine!: ElementRef<HTMLDivElement>; @HostListener('window:scroll', []) checkScroll() { if (!this.targetLine?.nativeElement) return; const line = this.targetLine.nativeElement; const windowHeight = window.innerHeight; const elementTop = line.getBoundingClientRect().top; const elementVisible = 150; if (elementTop < windowHeight - elementVisible) { line.classList.add('active-line'); } else { line.classList.remove('active-line'); } } }
对应HTML添加模板引用变量:
<div #targetLine class="mx-4 bd-highlight line"></div>
方案2:处理多个目标元素
如果页面存在多个.line元素,改用@ViewChildren批量获取:
import { Component, ElementRef, HostListener, ViewChildren, QueryList } from '@angular/core'; export class TestComponent { @ViewChildren('targetLine') targetLines!: QueryList<ElementRef<HTMLDivElement>>; @HostListener('window:scroll', []) checkScroll() { if (!this.targetLines?.length) return; const windowHeight = window.innerHeight; const elementVisible = 150; this.targetLines.forEach(lineEl => { const elementTop = lineEl.nativeElement.getBoundingClientRect().top; if (elementTop < windowHeight - elementVisible) { lineEl.nativeElement.classList.add('active-line'); } else { lineEl.nativeElement.classList.remove('active-line'); } }); } }
对应HTML给每个目标Div添加模板引用变量:
<div #targetLine class="mx-4 bd-highlight line"></div> <!-- 多个元素重复上述标签即可 -->
性能优化建议
添加防抖处理,避免滚动时频繁触发函数:
import { Component, ElementRef, HostListener, ViewChild, NgZone } from '@angular/core'; import { debounceTime, Subject } from 'rxjs'; export class TestComponent { @ViewChild('targetLine') targetLine!: ElementRef<HTMLDivElement>; private scrollSubject = new Subject<void>(); constructor(private ngZone: NgZone) {} ngOnInit() { this.ngZone.runOutsideAngular(() => { this.scrollSubject.pipe(debounceTime(50)).subscribe(() => { this.ngZone.run(() => this.updateLineClass()); }); }); } @HostListener('window:scroll', []) onScroll() { this.scrollSubject.next(); } private updateLineClass() { if (!this.targetLine?.nativeElement) return; const line = this.targetLine.nativeElement; const windowHeight = window.innerHeight; const elementTop = line.getBoundingClientRect().top; const elementVisible = 150; if (elementTop < windowHeight - elementVisible) { line.classList.add('active-line'); } else { line.classList.remove('active-line'); } } }
内容的提问来源于stack exchange,提问作者Abdalhmeed Shishani
相关产品推荐
相关产品推荐

