如何解决倒计时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()
}
})
```
解决方法
当涉及自定义元素/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
'逃脱' shadowDOM,因此所有 3 个计时器都在document
payloaddetail
报告他们的状态 -
按钮事件(所有按钮一个)是默认的
new Event(buttonlabel)
;它定位在host元素countdown
-
因此每个
<count-down
> 都捕获自己的按钮,事件不会到达其他元素 -
如果您希望事件上升到 DOM,您也可以为
new Event(buttonlabe,{...eventOptions})
添加选项 -
不是直接定位
countdown
您可以让按钮{bubbles:true,composed:false}
以便它们在其 shadowHost 中到达侦听器,但不要逃避 shadowDOM -
您可以在没有 shadowDOM 的情况下完成所有这些工作,这完全是关于定位(和/或冒泡)事件来自正确的 DOM 元素。
在这种情况下最惯用的可能是使用 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!
});
您可能还想查看这篇文章:
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。