javascript - 在循环中更改带有超时的图标
问题描述
我有以下代码循环遍历表中的每条记录并将保存图标设置为复选标记。
2 秒后,它应该变回保存图标。除非它没有。
我也对其他按钮使用了完全相同的方法,并且有效。所以我怀疑它与循环遍历每条记录的速度有关。虽然 setTimeout 应该是异步的......
有没有更好的方法来做到这一点?每个按钮都应该单独行动。我最后的手段是编写一个只更改页面上所有图标的函数,我宁愿不这样做。
const iconToggle = () => {
const isCheckIcon = btn.firstElementChild.classList.contains('fa-check');
if (isCheckIcon) {
btn.innerHTML = '<i class="fa fa-save fa-2x"></i>';
} else {
btn.innerHTML = '<i class="fa fa-check fa-2x"></i>';
}
}
for (row = 0; row < table.rows.length; row++) {
currentRow = table.rows.item(row);
...
returncode = save_row();
btn = currentRow.getElementsByClassName('record-save')[0].firstElementChild;
if (returncode == 0) {
iconToggle();
setTimeout(iconToggle, 2000);
}
}
编辑:
$('.table-save-all').on('click', 'i', function() {
var table = document.getElementById('edit_history_table_body');
const iconToggle = (abtn, state) => {
if (state == "save") {
abtn.innerHTML = '<i class="fa fa-save fa-2x"></i>';
} else if (state == "check") {
abtn.innerHTML = '<i class="fa fa-check fa-2x"></i>';
}
}
var currentRow, key, TotalNoBreakDec, OvertimeDec, TotalDec, StartDec, HourSchedule, returncode, btn;
// loop through each row of the table.
for (row = 0; row < table.rows.length; row++) {
currentRow = table.rows.item(row);
...
returncode = save_row();
btn = currentRow.getElementsByClassName('record-save')[0].firstElementChild;
if (returncode == 0) {
iconToggle(btn, "check");
setTimeout(() => { iconToggle(btn, "save") }, 2000);
}
}
btn = document.getElementsByClassName('table-save-all')[0].firstElementChild;
iconToggle(btn, "check");
setTimeout(() => { iconToggle(btn, "save") }, 2000);
});
解决方案
您应该将btn
要更改的参数作为参数传递给iconToggle()
方法。目前,您的循环会抛出所有按钮并重新分配 - 看似全局的 -btn
变量。因此,一旦触发重置图标的超时,btn
可能会分配给您的最后一个按钮,并且iconToggle
在超时中多次调用只需切换此按钮。
此外,我建议将所需状态传递给您的iconToggle
方法,以便始终清楚正在发生的变化以及错误调用iconToggle
不会以不需要的方式更新您的界面。
const iconToggle = (abtn, state) => {
if (state == "save") {
abtn.innerHTML = '<i class="fa fa-save fa-2x"></i>';
} else if (state == "check") {
abtn.innerHTML = '<i class="fa fa-check fa-2x"></i>';
}
}
for (row = 0; row < table.rows.length; row++) {
currentRow = table.rows.item(row);
...
returncode = save_row();
const btn = currentRow.getElementsByClassName('record-save')[0].firstElementChild;
if (returncode == 0) {
iconToggle(btn, "save");
setTimeout(() => {iconToggle(btn, "check")}, 2000);
}
}
编辑关于您的评论和答案中的更新代码:
将您的代码与我的代码进行比较。你会看到我有
const btn = ...
在循环体内,而你只有
btn = ...
因此,这行代码
setTimeout(() => {iconToggle(btn, "check")}, 2000);
在您的版本中,将引用btn
在循环体外部某处声明的变量(您没有显示在哪里)。btn
但是由于您在循环迭代期间以及循环之后不断更新此变量,btn
最终指向此元素
btn = document.getElementsByClassName('table-save-all')[0].firstElementChild;
这就是元素,所有iconToggles
超时回调都适用。
在循环体中声明btn
变量——或者在循环体中更好if
——它会起作用。
if (returncode == 0) {
const btn = currentRow.getElementsByClassName('record-save')[0].firstElementChild;
iconToggle(btn, "save");
setTimeout(() => {iconToggle(btn, "check")}, 2000);
}
所有变量都应该在尽可能小的范围内定义,以防止此类错误。
推荐阅读
- c++ - 在构造函数中将动态分配的数组分配给唯一的智能指针成员变量
- php - Php can't find tidy
- machine-learning - NLP初学者
- java - 如何在 Grails 的脚手架视图中显示 ID 列?
- android - 如何从字符串数组中获取随机值而不重复?
- css - 将列表组向右浮动
- django-rest-framework - 如果请求特定的 url,则更改模型字段
- java - 在我们的应用程序运行时面临 DDL 命令中的问题
- python-3.x - 无法使用 boto3 从 DynamoDB StringSet 中删除项目
- android - Camera2 MediaRecorder 改变 Galaxy S9 的帧速率