javascript 原生方法对dom节点的操作具体包括:创建、添加、删除、替换、插入、复制、移动等。
//查找节点
document.getElementById("id");// 通过id查找,返回唯一的节点
document.getElementsByClassName("class");// 通过class查找,返回值为nodeList类型
document.getElementsByTagName("div");// 通过标签名查找,返回值为nodeList类型
//创建节点
document.createDocumentFragment();//创建内存文档碎片
document.createElement();//创建元素
document.createTextNode();//创建文本节点
//添加节点
var ele = document.getElementById("my_div");
var oldEle = document.createElement("p");
var newEle=document.createElement("div");
ele.appendChild(oldEle);
//删除节点
ele.removeChild(oldEle);
//替换节点
ele.replaceChild(newEle,oldEle);
//插入节点
ele.insertBefore(oldEle,newEle);//在newEle之前插入 oldEle节点
//复制节点
var cEle = oldEle.cloneNode(true);//深度复制,复制节点下面所有的子节点
cEle = oldEle.cloneNode(false);//只复制当前节点,不复制子节点
//移动节点
var cloneEle = oldEle.cloneNode(true);//被移动的节点
document.removeChild(oldEle);//删除原节点
document.insertBefore(cloneEle,newEle);//插入到目标节点之前
dom操作场景
1.大量插入dom元素,例如向 <ul id="root"></ul> 插入1000条 <li>我是li标签</li> 标签。
DOM操作往往是JS程序中开销最大的部分,比如使用appendChild()方法,每次调用该方法时,浏览器都会重新渲染页面。如果大量的更新DOM节点,则会非常消耗性能,影响用户体验.
javascript提供了一个文档片段DocumentFragment的机制。如果将文档中的节点添加到文档片段中,就会从文档树中移除该节点。而把所有待构造的新节点都放在文档片段中去构造,这样可以不影响文档树,也就不会造成页面渲染。当所有新节点都构造完成后,再将文档片段对象添加到页面中,这时所有的新节点都会一次性渲染出来,从而减少浏览器负担。
<ul id="root"></ul>
<script>
var root = document.getElementById('root')
var fragment = document.createDocumentFragment()
for(let i = 0; i < 1000; i++){
let li = document.createElement('li')
li.innerHTML = '我是li标签'
fragment.appendChild(li)
}
root.appendChild(fragment);
</script>
2.节点移动
有这样的需求:源节点移动到目标节点的最后子节点位置上,注意源节点的子节点不随着移动。
初始dom结构
node2移动到node6后的结构
代码如下:
const moveNode=function (source, target) {
if(!source||!target) return;
let sourceNode = document.getElementById(source);
let sourceShadowClone=sourceNode.cloneNode(false);//对源节点的浅复制
let targetNode = document.getElementById(target);
let sParentNode = sourceNode.parentNode;
let sNextNode=sourceNode.nextElementSibling;
for(let i=0,len=sourceNode.childNodes.length;i<len;i++){
let sChildNode=sourceNode.lastElementChild;
// 由于 sChildNode是现有节点的引用,插入操作会使其从原先位置移动到指定位置,从而使 sourceNode.childNodes 中的节点数量减少
sParentNode.insertBefore(sChildNode,sNextNode);
sNextNode=sChildNode;
}
sParentNode.removeChild(sourceNode);
targetNode.appendChild(sourceShadowClone);
}
注意点:
1.NodeList
NodeList 以及 NamedNodeMap、HTMLColletion 都是动态的,每当文档结构改变时,它们都会得到更新(即始终保存着最新、最准确的文档结构信息)。本质上而言,所有 NodeList 对象都是在访问 DOM 文档时实时运行的查询。
所以以下代码会导致无限循环:
const divs=document.getElementsByTagName('div');
let i;
let div;
for(i=0;i<divs.length;i++){
div=document.createElement('div');
document.body.appendChild(div);
}
因为 document.getElementsByTagName 返回的是 HTMLCollection,所以每次获取其 length 时,都会实时进行页面上div元素的查找。这样每次新增一个div,divs的数量就加1,导致 变量 i 与 divs.length 同步增长,无限循环。要避免这种情况,可将 divs.length 保存在一个常量中。
2.Node.insertBefore()
在参考节点之前插入一个拥有指定父节点的子节点。
如果给定的子节点是对文档中现有节点的引用,insertBefore()会将其从当前位置移动到新位置(在将节点附加到其他节点之前,不需要从其父节点删除该节点)。
这意味着一个节点不能同时位于文档的两个点中。因此,如果节点已经有父节点,则首先删除该节点,然后将其插入到新位置。在将节点追加到新父节点之前,可以使用Node.clonenode()复制节点。注意,使用cloneNode创建的副本不会自动保持同步。
如果引用节点为空,则将指定的节点添加到指定父节点的子节点列表的末尾。
如果给定的子节点是DocumentFragment,那么DocumentFragment的全部内容将被移动到指定父节点的子节点列表中。







网友评论