【问题标题】:Custom event for countdown javascript倒计时javascript的自定义事件
【发布时间】:2021-04-08 09:00:21
【问题描述】:

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

  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()
    }
})
```

【问题讨论】:

  • "我在另一个自定义元素中调用我的自定义元素" - 请同时发布该代码。这是您应该安装事件侦听器的地方。您发布的计时器类只需要创建和调度事件。
  • 我希望我对帖子所做的更改足够清楚,否则请告诉我。
  • 如果您只需要在计时器到达 0 时运行一些代码,为什么不在 else { timer.textContent = '00:0' } 块内调用该代码?

标签: javascript custom-events


【解决方案1】:

在这种情况下最惯用的可能是使用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!
});

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

【讨论】:

    【解决方案2】:

    当涉及自定义元素/Web 组件时,Andrey 的回答将不会(总是)起作用。
    因为您明确需要设置事件如何冒泡或“逃脱”shadowDOM

    简化代码显示了 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' shadowDOM,因此所有 3 个计时器在 detail 中向 document 报告它们的状态有效负载

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

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

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

    • 您可以让按钮{bubbles:true, composed:false} 而不是直接定位countdown,以便它们到达其shadowHost 中的侦听器,但不要逃避shadowDOM

    • 您可以在没有 shadowDOM 的情况下完成所有这些操作,这一切都是为了将​​事件正确的 DOM 元素定位(和/或冒泡)。

    【讨论】:

    • 哦,你好,丹尼,纽约快乐! ??
    • 嗨,安德烈,好久不见。当他们开始使用 ReactJS for SharePoint 时,我离开了微软世界;我 100% 喜欢原生 Web 组件。有一个美好的 21
    • 是的,我也不再做太多 MS 了。 Web 组件很酷?!和你一样,在 21 世纪的 21 年过得愉快!!
    • iconmeister.github.io 是我最喜欢的项目之一;和 SP 天一样就是一切
    猜你喜欢
    • 1970-01-01
    • 2019-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多