由于RxJS的反跳,未显示默认浏览器工具提示

问题描述 投票:0回答:1

[我基本上想要实现的是监听文档中附加的'mousemove'事件,并且当我将鼠标悬停在元素上时,我检查它是否溢出了文本,并且是否将其截断并将title属性添加到具有全文本的目标元素因此,当用户将鼠标悬停在其上时,浏览器会显示带有此文本的默认工具提示。

此逻辑本身可以很好地工作,但存在重大缺陷。因为我在其中使用getComputedStyle(),所以它会破坏我的应用程序的性能。

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

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

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

问题是,有人知道如何解决此问题吗?

javascript dom browser rxjs
1个回答
0
投票

[嗯,我想您可以尝试使用mousemove方法在代码上触发Element.dispatchEvent()事件。我已经尝试在[stackblitz demo]中做一些示例(是的,它是有角度的,但是我没有使用Andy的角度功能,除了关注标记markup-javascript-css =>之外,其他所有东西都是纯JavaScript)。基本上我所做的是:

<p title="house">
  Start editing to see some magic happen :)
</p>
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;

  // track the elements that already has a title modified
  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
    })
  );
}

© www.soinside.com 2019 - 2024. All rights reserved.