有没有办法让添加事件侦听器先执行 mousedown,然后 mouseover,最后 mouseup?
Is there a way to have an add event listener first execute a mousedown, then mouseover, and finally mouseup?
所以现在我有一个 20 x 20 的网格,我希望用户能够单击并 select 网格中的多个单元格。我可以在网上找到一种方法,但问题是当鼠标悬停在单元格上时鼠标悬停接管并突出显示单元格,这不是我想要的。我希望用户单击一个单元格,然后基本上拖动他们的鼠标并突出显示他们想要的单元格,然后在他们放开后执行 mouseup。
这些是我的文件。
let graph = document.getElementById("container");
graph.style.display = "flex";
function createGraph() {
let j = 0;
for (let i = 0; i < 20; i++) {
let row = document.createElement("div");
row.id = "row" + i;
row.style.height = "50px";
row.style.width = "50px";
graph.appendChild(row);
let currentRow = document.getElementById("row" + i);
j++;
for (let j = 0; j < 20; j++) {
let cell = document.createElement("div");
cell.classList.add("cells");
///id's are used later in the project
cell.id = "index" + j + i;
cell.style.border = "1px solid black";
cell.style.height = "50px";
cell.style.width = "50px";
currentRow.appendChild(cell);
}
}
}
createGraph();
function main() {
document.querySelectorAll(".cells").forEach(item => {
["mousedown", "mouseover", "mouseup"].forEach(function(e) {
item.addEventListener(e, function() {
item.style.backgroundColor = "red";
})
})
})
}
main();
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<div id="container"></div>
</body>
</html>
所以在主要功能中,我为所有单元格添加了一个均匀的侦听器,并且我试图将它们的颜色更改为红色。问题是 mouseover 事件接管了 mousedown,这是我想要首先发生的。我怎样才能做到这一点,以便用户能够首先单击一个单元格,然后拖动他们的鼠标并继续突出显示单元格,一旦他们放开鼠标,突出显示就会停止。有没有办法先执行mousedown,再执行mouseover,最后执行mouseup?
像这样的技巧是只在 mousedown
上添加 mouseover
事件开始。 mouseover
无论如何,这通常是一个昂贵的事件(因为它会触发很多),所以您只在需要时“打开它”,在不需要时将其删除。
此外,如果您将同一事件关联到同一 parent 中的多个元素,最好 far 将事件分配给 parent 然后检查 target
并在它是您想要的 children 之一时采取行动(通常使用 .matches()
方法)。
然后,您不必担心 mousemove 先触发,因为它总是会触发第二个。请注意,每个单元格可能会触发多次,因此您需要编写代码来处理它。
let targetElements = [];
const parent = document.querySelector('.parent');
const mouseoverHandler = ({ target }) => {
if (!target.matches('.parent span')
|| targetElements.includes(target)) {
return;
}
targetElements.push(target);
};
parent.addEventListener('mousedown', ({ target }) => {
// use whatever selector makes sense for your children
if (!target.matches('.parent span')) return;
// reset the list here in case they mouseup-ed outside of the parent
targetElements = [];
// turn mouseover "on"
parent.addEventListener('mouseover', mouseoverHandler);
targetElements.push(target);
console.log('mouseover on');
});
parent.addEventListener('mouseup', ({ target }) => {
// use whatever selector makes sense for your children
if (!event.target.matches('.parent span')) return;
// turn mouseover "off"
parent.removeEventListener('mouseover', mouseoverHandler);
// do something with them
targetElements.forEach(el => el.classList.toggle('on'));
console.log('mouseover off');
});
.parent {
border: 2px solid #333;
width: 150px;
display: flex;
flex-wrap: wrap;
}
.parent span {
flex: 0 0 50px;
flex-wrap: wrap;
height: 50px;
border: 1px solid #CCC;
margin: -1px;
height: 50px;
display: -block;
}
.parent span:hover {
/* doesn't seem to work in the demo window */
background: #EEC;
cursor: pointer;
}
.parent span.on {
background: #F00;
}
<div class="parent">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
我稍微重构了你的代码。这是一个如何使用切换状态的简单示例:
let graph = document.getElementById('container');
function createGraph() {
for (let i = 0; i < 20; i++) {
let row = document.createElement('div');
row.id = 'row' + i;
row.className = 'rows';
for (let j = 0; j < 20; j++) {
let cell = document.createElement('div');
cell.className = 'cells';
cell.id = 'index' + j + i;
row.appendChild(cell);
}
graph.appendChild(row);
}
}
createGraph();
function main() {
let canSelect = false;
document.addEventListener('mousedown', () => canSelect = true);
document.addEventListener('mouseup', () => canSelect = false);
document.querySelectorAll('.cells').forEach(item => {
['mousedown', 'mouseover'].forEach(function(e) {
item.addEventListener(e, () => {
if (!canSelect && e !== 'mousedown') return;
item.style.backgroundColor = 'red';
})
})
})
}
main();
#container {
display: flex;
}
.rows, .cells {
width: 50px;
height: 50px;
}
.cells {
border: 1px solid black;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<div id="container"></div>
</body>
</html>
所以现在我有一个 20 x 20 的网格,我希望用户能够单击并 select 网格中的多个单元格。我可以在网上找到一种方法,但问题是当鼠标悬停在单元格上时鼠标悬停接管并突出显示单元格,这不是我想要的。我希望用户单击一个单元格,然后基本上拖动他们的鼠标并突出显示他们想要的单元格,然后在他们放开后执行 mouseup。
这些是我的文件。
let graph = document.getElementById("container");
graph.style.display = "flex";
function createGraph() {
let j = 0;
for (let i = 0; i < 20; i++) {
let row = document.createElement("div");
row.id = "row" + i;
row.style.height = "50px";
row.style.width = "50px";
graph.appendChild(row);
let currentRow = document.getElementById("row" + i);
j++;
for (let j = 0; j < 20; j++) {
let cell = document.createElement("div");
cell.classList.add("cells");
///id's are used later in the project
cell.id = "index" + j + i;
cell.style.border = "1px solid black";
cell.style.height = "50px";
cell.style.width = "50px";
currentRow.appendChild(cell);
}
}
}
createGraph();
function main() {
document.querySelectorAll(".cells").forEach(item => {
["mousedown", "mouseover", "mouseup"].forEach(function(e) {
item.addEventListener(e, function() {
item.style.backgroundColor = "red";
})
})
})
}
main();
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<div id="container"></div>
</body>
</html>
所以在主要功能中,我为所有单元格添加了一个均匀的侦听器,并且我试图将它们的颜色更改为红色。问题是 mouseover 事件接管了 mousedown,这是我想要首先发生的。我怎样才能做到这一点,以便用户能够首先单击一个单元格,然后拖动他们的鼠标并继续突出显示单元格,一旦他们放开鼠标,突出显示就会停止。有没有办法先执行mousedown,再执行mouseover,最后执行mouseup?
像这样的技巧是只在 mousedown
上添加 mouseover
事件开始。 mouseover
无论如何,这通常是一个昂贵的事件(因为它会触发很多),所以您只在需要时“打开它”,在不需要时将其删除。
此外,如果您将同一事件关联到同一 parent 中的多个元素,最好 far 将事件分配给 parent 然后检查 target
并在它是您想要的 children 之一时采取行动(通常使用 .matches()
方法)。
然后,您不必担心 mousemove 先触发,因为它总是会触发第二个。请注意,每个单元格可能会触发多次,因此您需要编写代码来处理它。
let targetElements = [];
const parent = document.querySelector('.parent');
const mouseoverHandler = ({ target }) => {
if (!target.matches('.parent span')
|| targetElements.includes(target)) {
return;
}
targetElements.push(target);
};
parent.addEventListener('mousedown', ({ target }) => {
// use whatever selector makes sense for your children
if (!target.matches('.parent span')) return;
// reset the list here in case they mouseup-ed outside of the parent
targetElements = [];
// turn mouseover "on"
parent.addEventListener('mouseover', mouseoverHandler);
targetElements.push(target);
console.log('mouseover on');
});
parent.addEventListener('mouseup', ({ target }) => {
// use whatever selector makes sense for your children
if (!event.target.matches('.parent span')) return;
// turn mouseover "off"
parent.removeEventListener('mouseover', mouseoverHandler);
// do something with them
targetElements.forEach(el => el.classList.toggle('on'));
console.log('mouseover off');
});
.parent {
border: 2px solid #333;
width: 150px;
display: flex;
flex-wrap: wrap;
}
.parent span {
flex: 0 0 50px;
flex-wrap: wrap;
height: 50px;
border: 1px solid #CCC;
margin: -1px;
height: 50px;
display: -block;
}
.parent span:hover {
/* doesn't seem to work in the demo window */
background: #EEC;
cursor: pointer;
}
.parent span.on {
background: #F00;
}
<div class="parent">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
我稍微重构了你的代码。这是一个如何使用切换状态的简单示例:
let graph = document.getElementById('container');
function createGraph() {
for (let i = 0; i < 20; i++) {
let row = document.createElement('div');
row.id = 'row' + i;
row.className = 'rows';
for (let j = 0; j < 20; j++) {
let cell = document.createElement('div');
cell.className = 'cells';
cell.id = 'index' + j + i;
row.appendChild(cell);
}
graph.appendChild(row);
}
}
createGraph();
function main() {
let canSelect = false;
document.addEventListener('mousedown', () => canSelect = true);
document.addEventListener('mouseup', () => canSelect = false);
document.querySelectorAll('.cells').forEach(item => {
['mousedown', 'mouseover'].forEach(function(e) {
item.addEventListener(e, () => {
if (!canSelect && e !== 'mousedown') return;
item.style.backgroundColor = 'red';
})
})
})
}
main();
#container {
display: flex;
}
.rows, .cells {
width: 50px;
height: 50px;
}
.cells {
border: 1px solid black;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<div id="container"></div>
</body>
</html>