倒计时的自定义事件 javascript

Custom event for countdown javascript

如何为计时器为零时创建自定义事件。我在另一个自定义元素中调用我的自定义元素,并且我希望在计时器为零时发生某些事情。我很难理解自定义事件,而且我正在努力了解如何在我的案例中使用自定义事件以及将事件侦听器放在哪里。 这是我的倒计时元素:

  class extends HTMLElement {
  constructor () {
      super()
      this.attachShadow({ mode: 'open' })
        .appendChild(template.content.cloneNode(true))
      this._div = this.shadowRoot.querySelector('div')
    }

    timer (limit = 20) {
      let startingTime = limit
      const timer = this.shadowRoot.querySelector('#timer')

      setInterval(updateInterval, 1000)

      function updateInterval () {
        if (startingTime >= 0) {
          const seconds = startingTime % 60
          timer.textContent = `00:${seconds}`
          startingTime--
        } else { timer.textContent = '00:0' }
      }
    }

    connectedCallback () {
      this.timer()
    }
  })

这是我调用倒计时元素的地方:

  customElements.define('quiz-questions',
  class extends HTMLElement {
   
    constructor () {
      super()
      this.attachShadow({ mode: 'open' })
        .appendChild(template.content.cloneNode(true))
      this._div = this.shadowRoot.querySelector('div')
      this._p = this.shadowRoot.querySelector('p')
      this._submit = this.shadowRoot.querySelector('#submit')
      this.result = []
    }

   timer (limit = 20) {
      const timer = document.createElement('countdown-timer')
      this._div.appendChild(timer)
      timer.timer(limit)
    }
  
   connectedCallback () {
      this.timer()
    }
})
```

在这种情况下最惯用的可能是使用 custom events:

const timerElement = this;
function updateInterval () {
    if (startingTime >= 0) {
        const seconds = startingTime % 60
        timer.textContent = `00:${seconds}`
        startingTime--
    } else {
        timer.textContent = '00:00'
        // dispatch a custom event
        const timeIsUpEvent = new CustomEvent('time-is-up');
        timerElement.dispatchEvent(timeIsUpEvent);
    }
}

然后在其他一些组件中:

this.addEventListener('time-is-up', (event) => {
    // do smth about it!
});

您可能还想看看这篇文章:

Andrey 当涉及自定义 Element/Web 组件时,他的回答不会(总是)有效。
因为您明确需要设置事件冒泡或“逃脱”阴影的方式DOM

简化代码显示了 2 个控制定时器的“开始”“停止”按钮;事件的多次使用

document.addEventListener("countdown", (evt) => {
  console.log("Timer Changed", evt.detail);
});
document.addEventListener("start", (evt) => {
  console.log("start event never reaches document");
});

let eventOptions = { bubbles: true, composed: true };

customElements.define("count-down", class extends HTMLElement {
    constructor() {
      super().attachShadow({mode: "open"})
             .append(document.getElementById(this.nodeName).content.cloneNode(true));
      this.paused = false;
      this.addEventListener("start", (evt) => this.paused = false);
      this.addEventListener("pause", (evt) => this.paused = true);
    }
    connectedCallback() {
      this.time = this.getAttribute("start") || 60;
      this.interval = setInterval(() => {
        this.innerHTML = this.paused ? this.time : this.time--;
        this.dispatchEvent(
          new CustomEvent("countdown", { ...eventOptions,
            detail: { id: this.id, time: this.time }
          })
        )}, 1000);
    }});
customElements.define("timer-buttons", class extends HTMLElement {
  connectedCallback() {
    let countdown = this.getRootNode().host;
    this.innerHTML = ["start","pause"].map(name =>`<button>${name}</button>`).join``;
    this.onclick = (evt) => countdown.dispatchEvent(new Event(evt.target.innerText));
  }});
<template id="COUNT-DOWN">
  <style>
    :host {
      display: inline-block;
      padding-right: 2em;
    }
    span {
      font-weight: bold;
    }
  </style>
  Timer: <slot></slot><span></span>
  <timer-buttons></timer-buttons>
</template>

<count-down id=ONE></count-down>
<count-down id=TWO start=42></count-down>
<count-down id=THREE start=21></count-down>

备注:

  • 使用了 2 种类型的事件

  • CustomEvent'escapes'影子DOM,所以所有3个计时器在detail[=]中向document报告它们的状态47=]有效负载

  • 按钮事件(所有按钮一个)是默认值new Event(buttonlabel);它的目标主机元素countdown

  • 所以每个 <count-down> 捕获自己的按钮,事件不会到达其他元素

  • 您也可以为 new Event(buttonlabe , {...eventOptions}) 添加选项,如果您希望事件上升到 DOM

  • 而不是直接定位 countdown 您可以让按钮 {bubbles:true, composed:false} 以便它们在其 shadowHost 中到达听众,但不要遁影DOM

  • 你可以在没有影子的情况下完成这一切DOM,这一切都是关于定位(and/or冒泡)事件来自正确的DOM 元素。