繁体   English   中英

平滑滚动会引发意外的未定义属性错误

[英]Smooth scroll throws unexpected undefined property error

我一直在尝试实现某种平滑滚动。 我按照这个代码笔创建了这样的卷轴: https : //codepen.io/osublake/pen/QqPqbN

我试着翻译成打字稿/角,但它在某种程度上仍然引发以下错误-不是当updateScroller()被调用的内部ngAfterViewInit ,但是当我尝试滚动的第一次-在指向const resized = this.scroller.resizeRequest > 0

core.js:9110 ERROR TypeError: Cannot read property 'scroller' of undefined
    at updateScroller (app.component.ts:50)
    at ZoneDelegate.invokeTask (zone-evergreen.js:391)
    at Object.onInvokeTask (core.js:34182)
    at ZoneDelegate.invokeTask (zone-evergreen.js:390)
    at Zone.runTask (zone-evergreen.js:168)
    at invokeTask (zone-evergreen.js:465)
    at ZoneTask.invoke (zone-evergreen.js:454)
    at timer (zone-evergreen.js:2650)
export class AppComponent implements OnInit, AfterViewInit {

  scroller = {
    target: document.querySelector('.scrollable-container'),
    ease: 0.05,
    endY: 0,
    y: 0,
    resizeRequest: 1,
    scrollRequest: 0,
  };

  requestId = null;

  constructor(@Inject(PLATFORM_ID) private platformId) {
  }

  ngOnInit() {
    if (isPlatformBrowser(this.platformId)) {
      console.log('Hi, this is NØREBRO!');
    }
  }

  ngAfterViewInit(): void {
    setTimeout(() => {
      this.scroller.target = document.querySelector('.scrollable-container');

      TweenLite.set(this.scroller.target, {
        rotation: 0.01,
        force3D: true
      });

      this.updateScroller();
    });
    window.focus();
  }

  updateScroller() {
    const html = document.documentElement;
    const body = document.body;

    const resized = this.scroller.resizeRequest > 0;

    if (resized) {
      const height = this.scroller.target.clientHeight;
      body.style.height = height + 'px';
      this.scroller.resizeRequest = 0;
    }

    const scrollY = window.pageYOffset || html.scrollTop || body.scrollTop || 0;

    this.scroller.endY = scrollY;
    this.scroller.y += (scrollY - this.scroller.y) * this.scroller.ease;

    if (Math.abs(scrollY - this.scroller.y) < 0.05 || resized) {
      this.scroller.y = scrollY;
      this.scroller.scrollRequest = 0;
    }

    TweenLite.set(this.scroller.target, {
      y: -this.scroller.y
    });

    this.requestId = this.scroller.scrollRequest > 0 ? requestAnimationFrame(this.updateScroller) : null;
  }

  @HostListener('window:scroll', [])
  scroll() {
    this.scroller.scrollRequest++;
    console.log(this.requestId);
    if (!this.requestId) {
      console.log('uff');
      this.requestId = requestAnimationFrame(this.updateScroller);
    }
  }

}

似乎this是通过重复方法调用undefined的。 在无法调试您的应用程序的情况下,我假设您需要this作为范围添加到您的this.updateScroller方法中。

函数的作用域 ( this ) 始终由执行上下文确定,并且通过requestAnimationFrame函数在类实例(组件)的上下文之外被调用。 有几篇关于函数作用域的有趣文章,例如见 这个

应该有两种方法可以解决您的问题:

a)将所有requestAnimationFrame(this.updateScroller)调用替换为

requestAnimationFrame(this.updateScroller.bind(this))

b)将所有requestAnimationFrame(this.updateScroller)调用替换为

requestAnimationFrame(() => {
  this.updateScroller()
})

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM