0

我正在使用 lit-element,并且有些地方需要添加滚动侦听器并运行一些函数,因此决定为此创建一个“服务”,它将 addEventListener 并可以将函数作为回调。在调用unsubscribeDomEvents()它时应该删除EventListener。

所以基本功能正在工作,但 removeEventListener 没有。_onScroll()即使在unsubscribeDomEvents()被调用之后,我仍然可以从中看到这个控制台。这是我现在拥有的:

const SCROLL_DOWN = 'scrollDown';

export class ScrollManager {
  private container: HTMLElement;
  private _callbacks = [];
  private readonly _scrollBind;

  constructor({ container }) {
    this._scrollBind = this._onScroll.bind(this);
    this.container = container;
    this.container.addEventListener('scroll', this._scrollBind);
  }

  onScrollDown(callback): ScrollManager {
    return this._registerCallback(SCROLL_DOWN, callback);
  }

  unsubscribeDomEvents(): void {
    this.container.removeEventListener('scroll', this._scrollBind);
  }

  private _registerCallback(callbackType: string, callback): ScrollManager {
    this._callbacks[callbackType] = callback;
    return this;
  }

  private _isScrollToBottom(container: HTMLElement): boolean {
    return container.scrollHeight - container.scrollTop - container.clientHeight < 1;
  }

  private _onScroll(): void {
    console.log('onscroll');
    if (this._isScrollToBottom(this.container)) {
      this._callbacks[SCROLL_DOWN]();
    }
  }
}

这是我在组件中使用它的方式

stateChanged(state: IState): void {
    ...
    this.isEditMode = state.modes.isEditMode;
    
    if (this.isEditMode) {
      this._scrollManager = new ScrollManager({ container: this.container })
              .onScrollDown(this.onScrollDown.bind(this));
    } else {
      this._scrollManager?.unsubscribeDomEvents();
    }

    this.requestUpdate();
  }

private onScrollDown(): void {
      // some function
}

将不胜感激任何帮助!

4

1 回答 1

1

面向未来的 Google 员工

您在这里正确地避免了一个常见错误:

this._scrollBind = this._onScroll.bind(this);

您保留对原始绑定函数的引用并取消订阅:

this.container.removeEventListener('scroll', this._scrollBind);

否则您将尝试取消订阅另一个功能

你的情况

观察你的stateChanged函数,如果它在isEditMode真实情况下多次触发,那么你将实例化ScrollManager两次,但取消订阅一次。

这是我认为正确的形式:

stateChanged(state: IState): void {
  ...
  this.isEditMode = state.modes.isEditMode;
  this._scrollManager?.unsubscribeDomEvents();
  if (this.isEditMode) {
    this._scrollManager = new ScrollManager({ container: this._scrolableContainer })
      .onScrollDown(this.onScrollDown.bind(this));
  }
  this.requestUpdate();
}
于 2021-08-31T11:13:07.687 回答