你的位置:首页 > Java教程

[Java教程]深入理解DOM节点操作


×
目录
[1]创建节点 [2]插入节点 [3]移除节点[4]替换节点[5]复制节点

前面的话

  一般地,提起操作会想到“增删改查”这四个字,而DOM节点操作也类似地对应于此,接下来将详细介绍DOM的节点操作方法

 

前提

  DOM提供节点操作的方法是因为DOM节点关系指针都是只读的

  下列代码中想通过修改myUl的父级节点来修改其节点关系,但由于parentNode属性是只读的,所以修改无效,在IE8-浏览器下甚至会报错

<div id="myDiv"></div><ul id="myUl">  <li id="myli"></li></ul><script>console.log(myUl.parentNode);//<body>myUl.parentNode = myDiv;//标准浏览器下,依然返回<body>;而IE8-浏览器则会报错console.log(myUl.parentNode);</script>

  DOM节点操作方法包括创建节点、插入节点、删除节点、替换节点、查看节点和复制节点。查看节点指的是查看节点之间的关系,在节点关系部分已经做过详细介绍,就不再赘述

 

创建节点

createElement

  document.createElement()方法可以创建新元素。这个方法接受一个参数,即要创建元素的标签名,这个标签名在HTML文档中不区分大小写

var oDiv = document.createElement("div");console.log(oDiv);//<div>

  IE8-浏览器可以为这个方法传入完整的元素标签,也可以包含属性

var oDiv = document.createElement('<div id="box"></div>');console.log(oDiv.id);//'box'

  所有节点都有一个ownerDocument的属性,指向表示整个文档的文档节点document;在使用createElement()方法创建新元素的同时,也为新元素设置了ownerDocument属性

<div id="myDiv"></div><script>console.log(myDiv.ownerDocument);//documentvar newDiv = document.createElement('div');console.log(newDiv.ownerDocument);//documentconsole.log(newDiv.ownerDocument === myDiv.ownerDocument);//true</script>

 

插入节点

appendChild

  appendChild()方法用于向childNodes列表的末尾添加一个节点,并返回新增节点。添加节点后,childNodes中的新增节点、父节点和以前的最后一个子节点的关系指针都会相应地得到更新

<div id="box"></div><script>var oBox = document.getElementById('box');var newNode = document.createElement('ul');var returnedNode = oBox.appendChild(newNode);console.log(returnedNode.nodeName);//ULconsole.log(returnedNode == newNode);//trueconsole.log(returnedNode == oBox.lastChild);//true</script>

  如果插入的节点已经是文档的一部分了,那结果就是将该节点从原来的位置转移到新位置

<body><div id="oldDiv">第一个div</div><div id="newDiv">第二个div</div><button id="btn">变换位置</button><script>btn.onclick = function(){  document.body.appendChild(newDiv);}  </script></body>

insertBefore

  insertBefore()方法接收两个参数:要插入的节点和作为参照的节点。插入节点后,被插入的节点会变成参照节点的前一个兄弟节点(previousSibling),同时被方法返回。如果参照节点是null,则insertBefore()与appendChild()方法执行相同的操作。同样地,如果插入的节点已经是文档的一部分了,那结果就是将该节点从原来的位置转移到新位置

referenceNode.parentNode.insertBefore(newNode,referenceNode);

<ul id="myUl" >  <li id="myLi">    <div id='oldDiv'>oldDiv</div>  </li>  </ul><button id="btn1">插入oldDiv的前面</button><button id="btn2">插入myUl的前面</button><button id="btn3">插到oldDiv的里面</button><script>var oDiv = document.createElement('div');oDiv.innerHTML = 'newDiv';btn1.onclick = function(){  console.log(myLi.insertBefore(oDiv,oldDiv));//<div>newDiv</div>}btn2.onclick = function(){  console.log(document.body.insertBefore(oDiv,myUl));//<div>newDiv</div>}btn3.onclick = function(){  console.log(oldDiv.insertBefore(oDiv,null));//<div>newDiv</div>}</script>

【小效果】

<ul id="list">  <li >1</li>  <li >2</li>  <li >3</li>  <li >4</li>  <li >5</li>  <li >6</li>    </ul><script>var oList = document.getElementById('list');//新增一个li元素var oAdd = document.createElement('li');//设置新增元素的css样式oAdd.className = "in";oAdd.style.cssText = 'background-color:red;border-radius:50%';//添加到oList中oList.insertBefore(oAdd,null);var num = -1;var max = oList.children.length;function incrementNumber(){  num++;  //oList.getElementsByTagName('li')[max]相当于null,所以不报错  oList.insertBefore(oAdd,oList.getElementsByTagName('li')[num]);    if(num == max){    num = -1;  }    if(num == 0){    num = 1;  }  setTimeout(incrementNumber,1000);}setTimeout(incrementNumber,1000);</script>

insertAfter

  由于不存在insertAfter方法,如果要插在当前节点的某个子节点后面,可以用insertBefore()和appendChild()封装方法

function insertAfter(newElement,targetElement){  var parent = targetElement.parentNode;  if(parent.lastChild == targetElement){    parent.appendChild(newElement);  }else{    parent.insertBefore(newElement,targetElement.nextSibling)  }}

<div id='oldDiv'>old</div><button id="btn">增加节点</button><script>function insertAfter(newElement,targetElement){  var parent = targetElement.parentNode;  if(parent.lastChild == targetElement){    return parent.appendChild(newElement);  }else{    return parent.insertBefore(newElement,targetElement.nextSibling)  }}  var newDiv = document.createElement('div');newDiv.innerHTML = 'new';btn.onclick = function(){  insertAfter(newDiv,oldDiv);}</script>

insertAdjacentHTML

  insertAdjacentHTML()方法作为终级办法,相当于前面三个方法的综合。该方法接收两个参数:插入的位置和要插入的HTML文本

  第一个参数必须是下列值之一,且这些值都必须是小写形式:

  "beforebegin"    在当前元素之前插入一个紧邻的同级元素  "afterbegin"    在当前元素之下插入一个新的子元素或在第一个子元素之前再插入新的子元素  "beforeend"    在当前元素之下插入一个新的子元素或在最后一个子元素之后再插入新的子元素  "afterend"     在当前元素之后插入一个紧邻的同级元素

  第二个参数是一个HTML字符串,如果浏览器无法解析字符串,就会抛出错误

  [注意]该方法无返回值

<div id='target' >This is the element content</div><button>beforebegin</button><button>afterbegin</button><button>beforeend</button><button>afterend</button><script>var btns = document.getElementsByTagName('button');for(var i = 0 ; i < 4; i++){  btns[i].onclick = function(){    var that = this;    target.insertAdjacentHTML(that.innerHTML,'<span id="test">测试</span>')    }}</script>  

移除节点

removeChild

  removeChild()方法接收一个参数,即要移除的节点,被移除的节点成为方法的返回值

<div id="myDiv">等待移除的节点</div><button id="btn">移除节点</button><script>btn.onclick = function(){  document.body.removeChild(myDiv);}</script>

  下面代码可以移除当前节点的所有子节点

var element = document.getElementById("top");while (element.firstChild) { element.removeChild(element.firstChild);}

【小效果】

<button id="btn">开始删除节点</button><ul id="list">  <li >1</li>  <li >2</li>  <li >3</li>  <li >4</li>  <li >5</li>  <li >6</li>    </ul><script>var oList = document.getElementById('list');function incrementNumber(){  //获取oList中子元素的个数  var len = oList.getElementsByTagName('li').length;  //如果长度不为0  if(len){    //删除最后一个子元素    oList.removeChild(oList.getElementsByTagName('li')[len-1]);    //再次调用计时器    setTimeout(incrementNumber,1000);    }}btn.onclick = function(){  //1s后执行函数incrementNumber  setTimeout(incrementNumber,1000);  }</script>

 

替换节点

replaceChild

  replaceChild()接收的两个参数是要插入的节点和要替换的节点,要替换的节点将由这个方法返回并从文档树中移除,同时由要插入的节点占据其位置

oldChild.parentNode.replaceChild(newChild, oldChild);

<div id="div1">1</div><div id="div2">2</div><div id="div3">3</div><button id="btn1">新增节点替换(4替换2)</button><button id="btn2">原有节点替换(3替换1)</button><script>btn2.onclick = function(){  document.body.replaceChild(div3,div1);}btn1.onclick = function(){  var div4 = document.createElement('div');  div4.innerHTML = '4';  document.body.replaceChild(div4,div2);}</script>

【小效果】

<button id="btn">开始替换节点</button><ul id="list">  <li >1</li>  <li >2</li>  <li >3</li>  <li >4</li>  <li >5</li>  <li >6</li>    </ul><script>var oList = document.getElementById('list');//新增一个li元素var oAdd = document.createElement('li');//设置新增元素的css样式oAdd.className = "in";oAdd.style.cssText = 'background-color:red;border-radius:50%';btn.onclick = function(){  //1s后oAdd替换第0个li  setTimeout(function(){    oList.replaceChild(oAdd,document.getElementsByTagName('li')[0]);    //1s后执行incrementNumber函数    setTimeout(incrementNumber,1000);    },1000);  }function incrementNumber(){  //获取oList中第1个li  var oLi1 = document.getElementsByTagName('li')[1];  //若存在则进行替换处理  if(oLi1){     oList.replaceChild(oAdd,oLi1);     setTimeout(incrementNumber,1000);      }}</script>

 

复制节点

cloneNode

  cloneNode方法用于克隆一个节点。它接受一个布尔值作为参数,表示是否执行深复制。在参数为true时,执行深复制,也就是复制节点及整个子节点树。在参数为false的情况下,执行浅复制,即复制节点本身。复制后返回的节点副本属于文档所有,但并没有为它指定父节点。若参数为空,也相当于false 

  [注意]cloneNode()方法不会复制添加到DOM节点中的javascript属性,例如事件处理程序等。这个方法只复制特性和子节点,其他一切都不会复制

<ul id="list">  <li>1</li>  <li>2</li>  <li>3</li>  <li>4</li>  <li>5</li>  <li>6</li>    </ul><script>var oList = document.getElementById('list');oList.index = 0;var deepList = oList.cloneNode(true);//成功复制了子节点console.log(deepList.children.length);//6//但并没有复制属性console.log(deepList.index);//undefinedvar shallowList = oList.cloneNode();//浅复制不复制子节点console.log(shallowList.children.length);//0</script>