调用scrollTo报Cannot read properties of undefined错误如何解决
报错原因
document.getElementsByClassName方法返回的是类数组格式的HTMLCollection集合,并非单个DOM元素,你直接对集合调用scrollTo方法自然会报错,需要先取下标获取集合内的单个元素才能调用对应方法。- 你的header元素绑定了
*ngIf="showMenu == 'home'"条件渲染规则,当跳转的页面不满足该判定条件时,这个header元素不会被挂载到DOM树中,你获取到的集合为空,即使取下标也会拿到undefined,调用scrollTo就会抛出你遇到的错误。 - 如果你的滚动逻辑是在路由跳转回调中同步执行,此时新页面的DOM还未完成渲染,也会出现获取不到元素的问题。
修复方案
方案1:最小改动修复现有逻辑
如果你需要保留现有手写滚动的逻辑,优先直接调用全局滚动方法,无需依赖特定DOM元素,同时增加执行时机和非空判断:
// 直接滚动整个页面到顶部,无需依赖header元素 window.scrollTo(0, 0); // 如果一定要滚动到header元素位置,改写成如下形式 const header = document.getElementsByClassName('homemenu')[0]; if (header) { header.scrollIntoView({ top: 0 }); }
同时要确保滚动逻辑在DOM渲染完成后执行,Angular项目中可以把滚动逻辑放在 ngAfterViewInit 生命周期钩子,或者在路由 NavigationEnd 事件回调中增加延迟执行:
import { NavigationEnd, Router } from '@angular/router'; import { filter } from 'rxjs'; constructor(private router: Router) {} ngOnInit() { this.router.events.pipe( filter(event => event instanceof NavigationEnd) ).subscribe(() => { setTimeout(() => { window.scrollTo(0, 0); }, 0) }) }
方案2:使用Angular原生路由滚动恢复能力(更推荐)
Angular路由本身内置了跳转后滚动位置控制能力,不需要手写DOM操作,直接在路由配置中开启即可:
在你的 app-routing.module.ts 中添加 scrollPositionRestoration 配置:
@NgModule({ imports: [RouterModule.forRoot(routes, { scrollPositionRestoration: 'top' // 每次路由跳转后自动滚动到页面顶部 })], exports: [RouterModule] }) export class AppRoutingModule { }
该方案是Angular原生支持的,性能更好,也不会出现DOM操作相关的异常。
内容的提问来源于stack exchange,提问作者Santosh
相关产品推荐
相关产品推荐

