คำแนะนำเครื่องมือเบราว์เซอร์เริ่มต้นไม่แสดงเนื่องจากการ debounce RxJS

โดยพื้นฐานแล้วสิ่งที่ฉันต้องการบรรลุคือการฟังเหตุการณ์ 'mousemove' ที่แนบมากับเอกสาร และเมื่อฉันวางเมาส์เหนือองค์ประกอบ ฉันจะตรวจสอบว่ามีข้อความล้นหรือไม่ และหากเป็นเช่นนั้น ฉันจะตัดทอนและเพิ่มแอตทริบิวต์ชื่อให้กับองค์ประกอบเป้าหมายด้วยข้อความแบบเต็ม เพื่อที่ เมื่อผู้ใช้วางเมาส์เหนือเบราว์เซอร์จะแสดงคำแนะนำเครื่องมือเริ่มต้นพร้อมข้อความนี้

ตรรกะนี้ทำงานได้ดีอย่างสมบูรณ์ แต่ก็มีข้อบกพร่องที่สำคัญ มันทำให้ประสิทธิภาพของแอพของฉันลดลงเพราะฉันใช้ getComputedStyle() อยู่ข้างใน

เพื่อแก้ไขปัญหานี้ ฉันพยายามใช้ RxJS debounce และใช้งานได้ดีมาก แต่หากผู้ใช้เลื่อนเมาส์อย่างรวดเร็วแล้วหยุดเพื่อให้มีเพียง 1 เหตุการณ์สำหรับองค์ประกอบนั้นที่ถูกปล่อยออกมา คำแนะนำเครื่องมือจะถูกเพิ่มใน DOM แต่ไม่แสดง

ตามที่ฉันเข้าใจสิ่งที่เกิดขึ้นจากมุมมองของเบราว์เซอร์ ทุกอย่างทำงานได้ดีเพราะเมื่อผู้ใช้วางเมาส์เหนือองค์ประกอบก็ยังไม่มีชื่อ และเมื่อเพิ่มเข้าไปแล้ว ผู้ใช้ก็จะไม่ขยับเมาส์อีกต่อไป ดังนั้นคำแนะนำเครื่องมือจึงไม่แสดง

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

คำถามคือมีใครรู้บ้างว่าฉันจะแก้ไขปัญหานี้ได้อย่างไร


person Mykola    schedule 23.03.2020    source แหล่งที่มา


คำตอบ (1)


ฉันคิดว่าคุณสามารถลองทริกเกอร์เหตุการณ์ mousemove บนโค้ดโดยใช้วิธี Element.dispatchEvent() ได้ ฉันได้ลองทำอะไรบางอย่างเป็นตัวอย่างใน stackblitz demo (ใช่ มันเป็นเชิงมุม แต่ฉันไม่ได้ใช้คุณลักษณะเชิงมุมของ andy นอกเหนือจากการแยกข้อกังวล markup-javascript-css => อย่างอื่นเป็นเพียง javascript ล้วนๆ) โดยพื้นฐานแล้วสิ่งที่ฉันทำคือ:

<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
    })
  );
}

person julianobrasil    schedule 24.03.2020