背景:
我想在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