网站搜索

typescript - Angular 6:TypeError:无法读取 null 的属性 'scrollIntoView'


我正在尝试在 Angular 6 中测试 scrollIntoView(),但是遇到了这个错误 --> TypeError: Cannot read property 'scrollIntoView' of null

规格 :

beforeEach(() => {
    fixture = TestBed.createComponent(BusinessInfoComponent);
    component = fixture.componentInstance;
    component.ngOnInit();
    spyOn(document.getElementById('info-banner'), 'scrollIntoView').and.callThrough(); 
    expect(document.getElementById('info-banner').scrollIntoView).toHaveBeenCalled();
    expect(document.getElementById('info-banner')).not.toBeDefined();
    fixture.detectChanges();
  });

ts :

ngOnInit() {
  document.getElementById('info-banner').scrollIntoView();

}

答案#1

document.getElementById('info-banner').scrollIntoView(); 应该放在 ngAfterViewInit() 生命周期钩子中。

基本上,任何 DOM 引用都应该放入那个钩子中。当 ngOnInit() 被执行时,DOM 还不存在,因此会出现错误。

答案#2

我尝试了之前的所有答案,但没有一个对我有效。我想出了一个解决方法:

⚠️⚠️ 警告 ⚠️⚠️:不推荐在企业应用中使用此代码。问题在于 myTarget 从 @ViewChild 变为已定义的时间不一定总是少于 50 毫秒,因此滚动可能不会 100% 执行。不过就性能而言,我认为这不是大问题。

话虽如此,到目前为止,这在我的应用中100%的情况下都有效,所以对于小型爱好/学校/大学项目来说,这是一个不错的变通方法。在我的应用中,等待总是少于3毫秒。你可以在你的应用中取消注释被注释掉的那一行,以查看你的组件需要多长时间。

async ngAfterViewInit() {
      let timesThat1MSWasWaited = 0;
      while (this.myTarget === undefined) {
        await new Promise(r => setTimeout(r, 1));
        if (timesThat1MSWasWaited > 50) {
          console.error('FatalException: Waited too long for highlighted song to appear in DOM.');
          return;
        }
        timesThat1MSWasWaited++;
      }
      // console.debug('Needed to wait at least ' + timesThat1MSWasWaited + 'ms for myTarget to appear.');

      this.myTarget.nativeElement.scrollIntoView({
        behavior: 'smooth',
        block: 'center',
      });
    }
  }