如何使用JavaScript/jQuery为动态添加的jQuery Sortable列表项添加正计时器
解决方案
核心错误点
- 创建计时节点的语法错误:
document.createElement()仅接受HTML标签名作为入参,你之前的写法无法生成合法的DOM节点,也无法绑定ID,导致计时器找不到操作目标 - 执行顺序错误:你先启动计时器再创建DOM节点,计时器首次运行时目标节点还未插入页面,直接报错导致功能失效
- 缺少Sortable刷新逻辑:动态添加列表项后需要手动刷新jQuery Sortable的识别缓存,否则新的列表项无法拖拽
修复后代码
function AddListItem() { const Name = "Mr Joe Bloggs"; const Age = "33 Years of Age"; let sec = 0; const pad = val => val > 9 ? val : "0" + val; // 创建列表项基础结构 const ul = document.getElementById("sortable1"); const li = document.createElement("li"); li.classList.add("ui-state-default"); li.appendChild(document.createTextNode(Name)); li.appendChild(document.createElement("br")); li.appendChild(document.createTextNode(Age)); li.appendChild(document.createElement("br")); // 创建计时节点,无需设置ID,直接通过闭包引用即可 const minutesEl = document.createElement("span"); const secondsEl = document.createElement("span"); // 初始化计时显示 minutesEl.innerText = pad(0); secondsEl.innerText = pad(0); // 组装节点 li.appendChild(minutesEl); li.appendChild(document.createTextNode(".")); // 如需冒号分隔直接替换此处内容即可 li.appendChild(secondsEl); ul.appendChild(li); // 刷新Sortable识别新的可拖拽项 $("#sortable1").sortable("refresh"); // 节点插入完成后启动计时器 setInterval(() => { sec++; secondsEl.innerText = pad(sec % 60); minutesEl.innerText = pad(parseInt(sec / 60, 10)); }, 1000); }
多列表项兼容优化
如果后续需要多次点击添加多个带计时器的列表项,直接使用上述代码即可,因为通过闭包引用了每个列表项专属的计时节点,不会出现ID重复冲突的问题。如果需要支持删除列表项,可以把setInterval的返回值存到li的自定义属性上,删除前先清除计时器避免内存泄漏:
// 存储计时器ID示例 li.dataset.timerId = setInterval(/* 计时器逻辑 */); // 删除列表项前清除计时器示例 clearInterval(Number(li.dataset.timerId)); li.remove();
内容的提问来源于stack exchange,提问作者William Hughes
相关产品推荐
相关产品推荐

