【问题标题】:Default browser tooltip is not shown because of RxJS debounce由于 RxJS 去抖动,默认浏览器工具提示未显示
【发布时间】:2020-07-04 03:12:12
【问题描述】:

基本上我想要实现的是收听附加到文档的“mousemove”事件,一旦我将鼠标悬停在元素上,我会检查它是否溢出了文本,如果是,我将其截断并将标题属性添加到具有完整的目标元素文本,以便当用户将鼠标悬停在其上时,浏览器会显示带有此文本的默认工具提示。

这个逻辑本身工作得很好,但它有很大的缺陷。它会降低我的应用程序的性能,因为我在其中使用了 getComputedStyle()。

为了解决这个问题,我尝试使用 RxJS debounce,效果很好。但是,如果用户快速移动鼠标然后停止,以便该元素仅发出 1 个事件,则工具提示将添加到 DOM 但不显示。

据我了解,从浏览器的角度来看,一切正常,因为当用户将鼠标悬停在元素上时,还没有标题,并且一旦添加,用户就不再移动鼠标,因此不会显示工具提示。

fromEvent(document, 'mouseenter')
.pipe(
  debounceTime(20),
  tap(($event: Event) => {
    this.addTooltip($event);
  })
)
.subscribe();

问题是有人知道我该如何解决这个问题吗?

【问题讨论】:

    标签: javascript dom browser rxjs


    【解决方案1】:

    好吧,我认为您可以尝试使用Element.dispatchEvent() 方法在代码上触发mousemove 事件。我试图在这个stackblitz demo 中做一些事情作为一个例子(是的,它是有角度的,但除了关注点分离标记-javascript-css => 其他一切都只是纯javascript)之外,我没有使用andy 角度特性。基本上我所做的是:

    <p title="house">
      Start editing to see some magic happen :)
    </p>
    
    // track the html elements that currently have a title modified
    // this avoids additional unnecessary listeners on a single HTML element
    private elementWithListenerAdded = new Set();
    
    ...
    
    fromEvent(document, "mousemove")
      .pipe(
        debounceTime(20),
        tap(($event: MouseEvent) => {
          this.addTooltip($event);
        })
      )
      .subscribe();
    
    ...
    
    addTooltip(evt: MouseEvent) {
      const $tag = evt.target;
    
      // I'm assuming that you don't want any tooltip on
      // header, HTML or body tags
      if (
        ($tag as any).tagName === "HEADER" ||
        ($tag as any).tagName === "HTML" ||
        ($tag as any).tagName === "BODY" ||
        this.elementWithListenerAdded.has($tag)
      ) {
        return;
      }
    
      const elementWithListenerAdded = this.elementWithListenerAdded;
    
      elementWithListenerAdded.add($tag);
    
      // remove the event listener when the mouse leave the element
      // and restore the original title
      const originalTitle = ($tag as any).getAttribute("title");
      function removeEventListener() {
        $tag.removeEventListener("mouseleave", this);
        elementWithListenerAdded.delete($tag);
        ($tag as any).setAttribute("title", originalTitle);
      }
    
      $tag.addEventListener("mouseleave", removeEventListener);
    
      ($tag as any).setAttribute("title", "just a test");
    
      ($tag as any).dispatchEvent(
        new MouseEvent("mousemove", {
          bubbles: true,
          cancelable: true,
          view: window
        })
      );
    }
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-13
      • 2012-09-14
      • 2017-08-07
      • 1970-01-01
      • 2013-07-30
      • 2014-11-13
      • 2022-01-02
      相关资源
      最近更新 更多