我有一个具有10000个单元格(100行和100列)的简单表,每个单元都有click事件侦听器。我没有发现任何视觉性能问题。您能否详细解释一下我,为什么对性能如此不利?
P.S。我知道事件冒泡,最好在.get()
上添加一个事件侦听器:)
<table>
const clickHandler = (event) => {
console.log(event);
};
const getTable = (rowsNum, columnsNum) => {
let row = '';
let rows = '';
for(let i = 0; i < columnsNum; ++i) {
row += '<td onclick="clickHandler(event)"></td>';
}
for(let i = 0; i < rowsNum; ++i) {
rows += `<tr>${row}</tr>`;
}
return `<table>${rows}</table>`
};
const innerTable = () => {
document.querySelector('.table').innerHTML = getTable(100, 100);
};
innerTable();
table, td {
border: 1px solid black;
}
td {
width: 5px;
height: 5px;
}
答案 0 :(得分:1)
...为什么对性能如此不利?
执行此操作时:
<td onclick="clickHandler(event)"></td>
您要让浏览器为每个td
生成一个函数,因为它必须为该字符串属性中的代码生成包装函数。那是浪费时间和记忆。
相反,如果您重用处理程序:
const table = document.querySelector('.table');
table.innerHTML = getTable(100, 100);
table.querySelectorAll("td").forEach(td => {
td.addEventListener("click", clickHandler);
});
显着地 更快:
const clickHandler = (event) => {
console.log(event.type);
};
const getTable = (rowsNum, columnsNum) => {
let row = '';
let rows = '';
for(let i = 0; i < columnsNum; ++i) {
row += '<td></td>';
}
for(let i = 0; i < rowsNum; ++i) {
rows += `<tr>${row}</tr>`;
}
return `<table>${rows}</table>`
};
const innerTable = () => {
const table = document.querySelector('.table');
table.innerHTML = getTable(100, 100);
table.querySelectorAll("td").forEach(td => {
td.addEventListener("click", clickHandler);
});
};
innerTable();
table, td {
border: 1px solid black;
}
td {
width: 5px;
height: 5px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="table">
</div>
<script src="script.js"></script>
</body>
</html>
如果进一步讲解并使用事件委托,甚至不需要循环调用addEventListener
(因此设置起来会更快一些),添加和删除表格单元格,它们将被自动处理:
const table = document.querySelector('.table');
table.innerHTML = getTable(100, 100);
table.addEventListener("click", clickHandler);
和
const clickHandler = (event) => {
const td = event.target.closest("td");
if (!td) {
return;
}
console.log(event.type);
};
const clickHandler = (event) => {
const td = event.target.closest("td");
if (!td) {
return;
}
console.log(event.type);
};
const getTable = (rowsNum, columnsNum) => {
let row = '';
let rows = '';
for(let i = 0; i < columnsNum; ++i) {
row += '<td></td>';
}
for(let i = 0; i < rowsNum; ++i) {
rows += `<tr>${row}</tr>`;
}
return `<table>${rows}</table>`
};
const innerTable = () => {
const table = document.querySelector('.table');
table.innerHTML = getTable(100, 100);
table.addEventListener("click", clickHandler);
};
innerTable();
table, td {
border: 1px solid black;
}
td {
width: 5px;
height: 5px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="table">
</div>
<script src="script.js"></script>
</body>
</html>
答案 1 :(得分:1)
一个事件处理程序将减少DOM和您自己管理的事件,这将使您更轻松,浏览器的性能也会更高。
事件委托是该模式的正确命名。它指的是使用冒泡处理DOM中更高级别的事件的过程。使用一个事件侦听器并在实际希望触发时过滤掉会更容易管理。
如果忘记删除事件侦听器,则可能会导致内存泄漏。
David Walsh提供了有关如何利用事件委托的不错的文章。 https://davidwalsh.name/event-delegate