我正在开发一个排行榜项目。这不是真实的东西,只是出于学习目的的演示,因为我是新手。
说到重点了。用户可以单击投票按钮,这将添加一票,将按钮上的信息更改为“感谢您投票”,最后禁用所有剩余按钮,因为在现实世界中,您通常每天可以投票一次。我花了一些时间,但还不错。
我想知道是否有一种简单的方法可以让用户更频繁地投票,假设每 10 秒投票一次。 我想允许它的原因是因为排行榜的内容是 JS 生成的,如果一个玩家比其他人获得更多的选票,他们将自动出现在排行榜上(然后我可能可以练习使用 localStorage 和某种类型的转换)。
投票功能的代码是这样的:
function voting() {
document.querySelectorAll('.vote-btn').forEach(button => {
button.addEventListener('click', (e) => {
button.innerHTML = 'thanks for voting!';
button.classList.replace(`vote-btn`, 'voted');
const target = e.target.closest('button');
const targetData = target.dataset.btnId;
if (targetData === playerPaul) {
document.getElementById(targetData).innerText = countPaul + 1;
disableVoting();
}
if 语句适用于所有玩家。
投票按钮已禁用:
function disableVoting() {
document.querySelectorAll('.vote-btn').forEach(button => {
button.disabled = true;
button.classList.add('no-cursor');
})
}
我的想法是添加另一个函数在给定时间后启动。 此功能将撤消禁用功能并允许再次投票。
function intervalVoting() {
document.querySelectorAll('.vote-btn').forEach(button => {
button.disabled = false;
button.classList.remove('no-cursor');
voting();
})
}
我尝试将
setInterval(intervalVoting, 10000)
添加到disableVoting(),如下所示:
function disableVoting() {
document.querySelectorAll('.vote-btn').forEach(button => {
button.disabled = true;
button.classList.add('no-cursor');
setInterval(intervalVoting, 10000);
})
}
什么是它允许在 10 秒后再次投票,但仅限于尚未投票的玩家。
任何更容易重构的实现都会选择一种引入原子任务的方法,这些任务被实现为有意义的命名函数语句。
此外,根据标记,可以选择事件委托,以便不必单独为每个投票按钮订阅自己的处理程序函数。
还可以删除一些 CSS 类名,转而采用更通用、更具表现力的基于选择器的样式规则。
function updateVoteCount(target) {
const countValue = parseInt(target.dataset.voteCount, 10) + 1;
target.dataset.voteCount = countValue;
target.textContent = countValue;
}
function restoreVoting(target) {
target.classList.remove('voted');
target.textContent = target.dataset.btnTextBeforeVote;
target.disabled = false;
}
function temporarilyDisableVoting(target) {
target.disabled = true;
setTimeout(restoreVoting, 10_000, target);
}
function temporarilyDisableAnyListItemVoting(listRoot) {
listRoot
.querySelectorAll('.vote-btn')
.forEach(temporarilyDisableVoting);
}
function handlePlayerListItemVote({ target }) {
target = target.closest('.vote-btn');
const listRoot = target && target.closest('.player-list');
if (listRoot !== null) {
temporarilyDisableAnyListItemVoting(listRoot);
target.classList.add('voted');
target.textContent = target.dataset.btnTextAfterVote;
updateVoteCount(
target.closest('li').querySelector('[data-vote-count]')
);
}
}
document
.querySelector('.player-list')
.addEventListener('click', handlePlayerListItemVote);
body { margin: 0; }
p { margin: 5px 0; }
button.vote-btn:not(:disabled) { cursor: pointer; }
button.vote-btn.voted { background-color: #cf0; }
<ul class="player-list">
<li>
<p>
Player Foo - upvotes:
<span data-vote-count="0">0</span>
</p>
<button
class="vote-btn"
data-btn-text-after-vote="thanks for voting!"
data-btn-text-before-vote="feel free to vote"
>feel free to vote</button>
</li>
<li>
<p>
Player Bar - upvotes:
<span data-vote-count="0">0</span>
</p>
<button
class="vote-btn"
data-btn-text-after-vote="thanks for voting!"
data-btn-text-before-vote="feel free to vote"
>feel free to vote</button>
</li>
<li>
<p>
Player Baz - upvotes:
<span data-vote-count="0">0</span>
</p>
<button
class="vote-btn"
data-btn-text-after-vote="thanks for voting!"
data-btn-text-before-vote="feel free to vote"
>feel free to vote</button>
</li>
</ul>