背景:
我想在html
3个ul
中动态生成5个子元素li
目标效果:
废话少说,代码直接梭起来~
1. 先写html
结构
<section class="list-box"> <ul id="myList"></ul> <ul id="myListOne"></ul> <ul id="myListTwo"></ul> </section>
2. 动态渲染子元素li
不就是写个for
循环呗,并且我还加了class
属性item
for (var i = 1; i <= 5; i++) { var listItem = document.createElement("li"); listItem.setAttribute('class', 'item') document.getElementById("myList").appendChild(listItem); document.getElementById("myListOne").appendChild(listItem); document.getElementById("myListTwo").appendChild(listItem); }
3. 失败,没达到预期效果
心想这个简单,很自信的打开浏览器查阅效果
哦豁?怎么回事?只有一列?
不应该呢,赶紧F12
打开控制台查看
两个问号
myList
和myListOne
怎么没有渲染出子元素li
呢?- 为什么只有
myListTwo
渲染出来子元素?
返回查看代码
难道是 var
定义变量的问题么?
好,修改成let
还是一样只有一列,有点迷了~
4. 查阅资料
查阅资料中......
嘿!好家伙 还真的找到了,开心!
MDN官方文档 API:appendChild
MDN官方文档 API:cloneNode
5. 分析原因
在每次迭代时,listItem
都会被添加到myList
、myListOne
和myListTwo
中。但是,由于 DOM (文档对象模型) 的规则限制,一个 DOM 元素节点在同一时刻只能存在于 DOM 树的一个位置。 也就是说,在每次循环迭代时,都需要创建新的li
元素节点,而不是重复使用同一个listItem。因此,当listItem
被添加到myListTwo
之后,它就从myList
和myListOne
中被移除了,因为它已经成为了myListTwo
的子元素。
6. 解决问题
两个解决办法:
(1). 用Node.cloneNode()
api进行克隆一份副本,每个节点进行单独appendChild()
for (let i = 1; i <= 5; i++) { let listItem = document.createElement("li"); listItem.setAttribute('class', 'item') document.getElementById("myList").appendChild(listItem); let listItemOne = listItem.cloneNode(true); //true 深度克隆 li下面所有子节点 listItemOne.setAttribute('class', 'item') document.getElementById("myListOne").appendChild(listItemOne); let listItemTwo = listItem.cloneNode(true); listItemTwo.setAttribute('class', 'item') document.getElementById("myListTwo").appendChild(listItemTwo); }
(2). 可以通过将listItem = document.createElement("li")
,每个节点进行单独appendChild()
for (let i = 1; i <= 5; i++) { let listItem = document.createElement("li"); listItem.setAttribute('class', 'item') document.getElementById("myList").appendChild(listItem); let listItemOne = document.createElement("li"); listItemOne.setAttribute('class', 'item') document.getElementById("myListOne").appendChild(listItemOne); let listItemTwo = document.createElement("li"); listItemTwo.setAttribute('class', 'item') document.getElementById("myListTwo").appendChild(listItemTwo); }
查看效果,成功解决
7. 优化代码
上面两种解决办法都存在相同的代码,抽离出来
// 定义一个创建并设置属性的函数 function createListItem(className) { let listItem = document.createElement("li"); listItem.setAttribute('class', className); return listItem; } // 在循环中调用函数创建并添加 <li> 元素 for (let i = 1; i <= 5; i++) { let listItem = createListItem('item'); document.getElementById("myList").appendChild(listItem); let listItemOne = createListItem('item'); document.getElementById("myListOne").appendChild(listItemOne); let listItemTwo = createListItem('item'); document.getElementById("myListTwo").appendChild(listItemTwo); }
溜了~
继续写BUG~
本文来自博客园,作者:书中枫叶,转载请注明原文链接:https://www.cnblogs.com/zy-mg/p/17322663.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?