这是我对投票制度的尝试。如果只有一个,它就会像预期的那样工作。然而,当我试图扩大投票系统的数量超过一个,它并不像预期的那样工作。问题是投票系统依赖于upVote和downVote状态。因此,当我增加投票系统的数量时,它们都依赖于相同的两个变量,而不是每个变量都有自己的upVote和downVote变量。我认为有两种方法可以解决我的问题。
upVote和downVote变量。第一个我认为过于繁琐和不切实际--我不知道如何实现这个解决方案。第二次,我试过了,但没能成功。
我想不出更简单的事了。我不一定要寻找一个使用闭包的解决方案。任何简单的香草Javascript解决方案都可以。
工作守则:
const up_vote_span = document.querySelector('.up-vote');
const down_vote_span = document.querySelector('.down-vote');
let count = document.querySelector('.number');
let upVote = false;
let downVote = false;
up_vote_span.addEventListener('click', function() {
if (downVote === true) {
up_vote_span.style.color = "#3CBC8D";
down_vote_span.style.color = "dimgray";
count.innerHTML = parseInt(count.innerHTML) + 2;
upVote = true;
downVote = false;
} else if (upVote === false) {
up_vote_span.style.color = "#3CBC8D";
count.innerHTML = parseInt(count.innerHTML) + 1;
upVote = true;
} else if (upVote === true) {
up_vote_span.style.color = "dimgray";
count.innerHTML = parseInt(count.innerHTML) - 1;
upVote = false;
}
});
down_vote_span.addEventListener('click', function() {
if (upVote === true) {
up_vote_span.style.color = "dimgray";
down_vote_span.style.color = "#3CBC8D";
count.innerHTML = parseInt(count.innerHTML) - 2;
downVote = true;
upVote = false;
} else if (downVote === false) {
down_vote_span.style.color = "#3CBC8D";
count.innerHTML = parseInt(count.innerHTML) - 1;
downVote = true;
} else if (downVote === true) {
down_vote_span.style.color = "dimgray";
count.innerHTML = parseInt(count.innerHTML) + 1;
downVote = false;
}
});.number {
display: inline-block;
text-align: center;
}
.vote {
display: flex;
flex-direction: column;
text-align: center;
}
.up-vote {
color: dimgray;
cursor: pointer;
}
.down-vote {
cursor: pointer;
color: dimgray;
}<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
</head>
<div class="vote">
<span class="up-vote"><i class="fas fa-angle-up"></i></span>
<span class="number">990</span>
<span class="down-vote"><i class="fas fa-angle-down"></i></span>
</div>
有问题的代码:
const up_vote_span = document.getElementsByClassName('up-vote');
const down_vote_span = document.getElementsByClassName('down-vote');
const count = document.getElementsByClassName('number');
let upVote = false;
let downVote = false;
for (let i = 0; i < count.length; i++) {
up_vote_span[i].addEventListener('click', function() {
if (downVote === true) {
up_vote_span[i].style.color = "#3CBC8D";
down_vote_span[i].style.color = "dimgray";
count[i].innerHTML = parseInt(count[i].innerHTML) + 2;
upVote = true;
downVote = false;
} else if (upVote === false) {
up_vote_span[i].style.color = "#3CBC8D";
count[i].innerHTML = parseInt(count[i].innerHTML) + 1;
upVote = true;
} else if (upVote === true) {
up_vote_span[i].style.color = "dimgray";
count[i].innerHTML = parseInt(count[i].innerHTML) - 1;
upVote = false;
}
});
down_vote_span[i].addEventListener('click', function() {
if (upVote === true) {
up_vote_span[i].style.color = "dimgray";
down_vote_span[i].style.color = "#3CBC8D";
count[i].innerHTML = parseInt(count[i].innerHTML) - 2;
downVote = true;
upVote = false;
} else if (downVote === false) {
down_vote_span[i].style.color = "#3CBC8D";
count[i].innerHTML = parseInt(count[i].innerHTML) - 1;
downVote = true;
} else if (downVote === true) {
down_vote_span[i].style.color = "dimgray";
count[i].innerHTML = parseInt(count[i].innerHTML) + 1;
downVote = false;
}
});
}.number {
display: inline-block;
text-align: center;
}
.vote {
display: flex;
flex-direction: column;
text-align: center;
}
.up-vote {
color: dimgray;
cursor: pointer;
}
.down-vote {
cursor: pointer;
color: dimgray;
}<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
</head>
<body>
<div class="vote">
<span class="up-vote"><i class="fas fa-angle-up"></i></span>
<span class="number">990</span>
<span class="down-vote"><i class="fas fa-angle-down"></i></span>
</div>
<div class="vote">
<span class="up-vote"><i class="fas fa-angle-up"></i></span>
<span class="number">990</span>
<span class="down-vote"><i class="fas fa-angle-down"></i></span>
</div>
<div class="vote">
<span class="up-vote"><i class="fas fa-angle-up"></i></span>
<span class="number">990</span>
<span class="down-vote"><i class="fas fa-angle-down"></i></span>
</div>
<div class="vote">
<span class="up-vote"><i class="fas fa-angle-up"></i></span>
<span class="number">990</span>
<span class="down-vote"><i class="fas fa-angle-down"></i></span>
</div>
</body>
</html>
发布于 2019-03-21 05:15:30
我认为您会发现这更容易控制,如果您使用您提到的数组方法作为选项1,然后创建一个用于向上的函数和一个用于下垂的函数,而不是像现在这样为每个向上和向下箭头创建单独的函数。
现在有四个组,所以在for循环中我们可以初始化一个数组,如下所示:
const votes = [
0: { up: false, down: false },
1: { up: false, down: false },
2: { up: false, down: false },
3: { up: false, down: false },
];然后,您只需调用您的向上和向下投票函数,并检查该数组中对象的值,该对象对应于您单击的箭头的组号。
另一件我认为有助于可读性的事情是把投票总数和颜色变化分开。
你的投票逻辑包括三种不同的可能性。2.箭头已被选中)对箭头进行检查,3.)两个箭头都没有被检查。但是,更改颜色的逻辑和更改每个箭头的检查值的逻辑实际上只有两种可能性:要么之前检查箭头,要么没有检查箭头。
所以我继续在下面的片段中做了这个改变。
希望这能有所帮助。
const up_vote_spans = document.getElementsByClassName('up-vote');
const down_vote_spans = document.getElementsByClassName('down-vote');
const count = document.getElementsByClassName('number');
let votes = [];
for (let i = 0; i < count.length; i += 1) {
const thisUpVoteSpan = up_vote_spans[i];
const thisDownVoteSpan = down_vote_spans[i];
votes[i] = { up: false, down: false };
thisUpVoteSpan.addEventListener('click', handleUpvote.bind(null, i), false);
thisDownVoteSpan.addEventListener('click', handleDownvote.bind(null, i), false);
}
function handleUpvote(i) {
const currentVote = votes[i];
const matchingUpSpan = up_vote_spans[i];
const matchingDownSpan = down_vote_spans[i];
const matchingCount = count[i];
const currentCount = parseInt(matchingCount.innerHTML);
if (currentVote.down) {
matchingCount.innerHTML = currentCount + 2;
} else if (currentVote.up === false) {
matchingCount.innerHTML = currentCount + 1;
} else {
matchingCount.innerHTML = currentCount - 1;
}
if (!currentVote.up) {
matchingUpSpan.style.color = "#3CBC8D";
matchingDownSpan.style.color = 'dimgray';
currentVote.up = true;
currentVote.down = false;
} else {
matchingUpSpan.style.color = 'dimgray';
currentVote.up = false;
}
}
function handleDownvote(i) {
const currentVote = votes[i];
const matchingUpSpan = up_vote_spans[i];
const matchingDownSpan = down_vote_spans[i];
const matchingCount = count[i];
const currentCount = parseInt(matchingCount.innerHTML);
if (currentVote.up) {
matchingCount.innerHTML = currentCount - 2;
} else if (currentVote.down === false) {
matchingCount.innerHTML = currentCount - 1;
} else {
matchingCount.innerHTML = currentCount + 1;
}
if (!currentVote.down) {
matchingDownSpan.style.color = "#3CBC8D";
matchingUpSpan.style.color = 'dimgray';
currentVote.down = true;
currentVote.up = false;
} else {
matchingDownSpan.style.color = 'dimgray';
currentVote.down = false;
}
}.number {
display: inline-block;
text-align: center;
}
.vote {
display: flex;
flex-direction: column;
text-align: center;
}
.up-vote {
color: dimgray;
cursor: pointer;
}
.down-vote {
cursor: pointer;
color: dimgray;
}<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
</head>
<body>
<div class="vote">
<span class="up-vote"><i class="fas fa-angle-up"></i></span>
<span class="number">990</span>
<span class="down-vote"><i class="fas fa-angle-down"></i></span>
</div>
<div class="vote">
<span class="up-vote"><i class="fas fa-angle-up"></i></span>
<span class="number">990</span>
<span class="down-vote"><i class="fas fa-angle-down"></i></span>
</div>
<div class="vote">
<span class="up-vote"><i class="fas fa-angle-up"></i></span>
<span class="number">990</span>
<span class="down-vote"><i class="fas fa-angle-down"></i></span>
</div>
<div class="vote">
<span class="up-vote"><i class="fas fa-angle-up"></i></span>
<span class="number">990</span>
<span class="down-vote"><i class="fas fa-angle-down"></i></span>
</div>
</body>
</html>
发布于 2019-03-21 05:26:45
我正在使用原型模式来组织代码。
这将适用于n .vote类在HTML中。例如,给定以下HTML,将创建两个投票对象,并将其与各自的UI相关联。
<div class="vote">
<span class="up-vote"><i class="fas fa-angle-up"></i></span>
<span class="number">0</span>
<span class="down-vote"><i class="fas fa-angle-down"></i></span>
</div>
<div class="vote">
<span class="up-vote"><i class="fas fa-angle-up"></i></span>
<span class="number">0</span>
<span class="down-vote"><i class="fas fa-angle-down"></i></span>
</div>您可能已经注意到,在上面的id中没有HTML。id在forEach循环中动态创建,并在每个对象的init上分配。我使用myVotePrototype作为模板,将其prototype复制到在myVote中创建的每个新对象中。myVote需要一个id来初始化,这就是每个投票都知道在哪里找到其关联的UI部分的方式。
颜色呢?
JavaScript在.vote父容器中设置投票方向。因此,在进行了向上投票之后,该投票对象的HTML将如下所示:
<div class="vote vote-up">
<span class="up-vote"><i class="fas fa-angle-up"></i></span>
<span class="number">0</span>
<span class="down-vote"><i class="fas fa-angle-down"></i></span>
</div>我添加了一个小的CSS,这样每个按钮都知道什么时候应该使用活动的颜色。我发现这比将十六进制代码直接写到style属性要麻烦得多。
.vote.vote-up .up-vote,
.vote.vote-down .down-vote {
color: #3CBC8D;
}演示
const myVotePrototype = {
init: function(id) {
this.voteId = id;
// Prepare for voting clicks
this.bindEvents();
},
votes: 0,
upVote: function() {
this.votes++;
this.setVoteDirection('up');
},
downVote: function() {
this.votes--;
this.setVoteDirection('down');
},
setVoteDirection: function(direction) {
let voteObj = document.getElementById(this.voteId);
if (direction === 'up') {
voteObj.classList.add('vote-up');
if (voteObj.classList.contains('vote-down')) {
voteObj.classList.remove('vote-down');
}
} else if (direction === 'down') {
voteObj.classList.add('vote-down');
if (voteObj.classList.contains('vote-up')) {
voteObj.classList.remove('vote-up');
}
}
},
updateUI: function() {
document.querySelector(`#${this.voteId} .number`).innerHTML = Number(this.votes);
},
bindEvents: function() {
document
.querySelector(`#${this.voteId} .up-vote`)
.addEventListener('click', () => {
this.upVote();
this.updateUI();
});
document
.querySelector(`#${this.voteId} .down-vote`)
.addEventListener('click', () => {
this.downVote();
this.updateUI();
})
}
};
function myVote(id) {
function V() {};
V.prototype = myVotePrototype;
let v = new V();
v.init(id);
return v;
}
// Loop through all votes in the UI
const votes = document.querySelectorAll('.vote');
votes.forEach((vote, index) => {
// Create an id
let voteId = `vote_${index}`;
// Set the id in the UI so we can find it later for updating
vote.setAttribute('id', voteId);
// Create a new vote object, passing in the vote id
myVote(voteId);
});.number {
display: inline-block;
text-align: center;
}
.vote {
display: flex;
flex-direction: column;
text-align: center;
}
.up-vote,
.down-vote {
color: dimgray;
cursor: pointer;
}
.vote.vote-up .up-vote,
.vote.vote-down .down-vote {
color: #3CBC8D;
}<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
<div class="vote">
<span class="up-vote"><i class="fas fa-angle-up"></i></span>
<span class="number">0</span>
<span class="down-vote"><i class="fas fa-angle-down"></i></span>
</div>
<div class="vote">
<span class="up-vote"><i class="fas fa-angle-up"></i></span>
<span class="number">0</span>
<span class="down-vote"><i class="fas fa-angle-down"></i></span>
</div>
<div class="vote">
<span class="up-vote"><i class="fas fa-angle-up"></i></span>
<span class="number">0</span>
<span class="down-vote"><i class="fas fa-angle-down"></i></span>
</div>
改进的思路
HTML (<button>而不是<span>)button与number输出相关联localStorage来记住页面加载之间的投票状态(或者使用真正的DB:)发布于 2019-03-21 05:27:07
就我个人而言,我认为一系列投票的布尔人并不坏。但是,如果您想要一种不同的方法,您可以使用类操作来保持它们的分离。
JSFiddle:https://jsfiddle.net/0uw83a17/
// From https://plainjs.com/javascript/traversing/get-siblings-of-an-element-40/
function getSiblings(el, filter) {
var siblings = [];
el = el.parentNode.firstChild;
do { if (!filter || filter(el)) siblings.push(el); } while (el = el.nextSibling);
return siblings;
}
function classFilter(el) {
return el.classList && el.classList.contains('active-vote');
}
function handleVote(type, el) {
let siblings = getSiblings(el, classFilter);
if (el.classList.contains('active-vote')) {
el.style.color = "dimgray";
el.classList.remove('active-vote');
return -1 * type;
} else if (siblings.length === 1) {
el.style.color = "#3CBC8D";
siblings[0].style.color = "dimgray";
siblings[0].classList.remove('active-vote');
el.classList.add('active-vote');
return 2 * type;
} else if (!el.classList.contains('active-vote')) {
el.style.color = "#3CBC8D";
el.classList.add('active-vote');
return type;
}
return 0;
}
const up_vote_span = document.getElementsByClassName('up-vote');
const down_vote_span = document.getElementsByClassName('down-vote');
const count = document.getElementsByClassName('number');
for (let i = 0; i < count.length; i++) {
up_vote_span[i].addEventListener('click', function(e) {
count[i].innerHTML = parseInt(count[i].innerHTML) + handleVote(1, up_vote_span[i]);
});
down_vote_span[i].addEventListener('click', function() {
count[i].innerHTML = parseInt(count[i].innerHTML) + handleVote(-1, down_vote_span[i]);
});
};https://stackoverflow.com/questions/55273716
复制相似问题