前面的话

  一般地,提起操作会想到“增删改查”这四个字,而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'

  利用这种方法可以避开IE7-浏览器在动态创建元素的下列问题  

  1、不能设置动态创建的<iframe>元素的name特性

  2、不能通过表单的reset()方法重设动态创建的<input>元素

  3、动态创建的type特性值为"reset"的<button>元素重设不了表单

  4、动态创建的一批name相同的单选按钮彼此毫无关系。name值相同的一组单选按钮本来应该用于表示同一选项的不同值,但动态创建的一批这种单选按钮之间却没有这种关系

var iframe = document.createElement("<iframe name = 'myframe'></iframe>");
var input = document.createElement("<input type='checkbox'>);
var button = document.createElement("<button type = 'reset'></button>");
var radio1 = document.createElement("<input type='radio' name ='choice' value = '1'>");
var radio2 = document.createElement("<input type='radio' name ='choice' value = '2'>");

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

<div id="myDiv"></div>
<script>
console.log(myDiv.ownerDocument);//document
var newDiv = document.createElement('div');
console.log(newDiv.ownerDocument);//document
console.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);//UL
console.log(returnedNode == newNode);//true
console.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" style="border:1px solid black;">
<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 class="list" id="list">
<li class="in">1</li>
<li class="in">2</li>
<li class="in">3</li>
<li class="in">4</li>
<li class="in">5</li>
<li class="in">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' style="border: 1px solid black;">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 class="list" id="list">
<li class="in">1</li>
<li class="in">2</li>
<li class="in">3</li>
<li class="in">4</li>
<li class="in">5</li>
<li class="in">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>

remove()

  相比于removeChild(),remove()方法不太常见,但是却非常简单。该方法不用调用其父节点,直接在当前节点使用remove()方法就可以删除该节点,无返回值

  remove()方法常用于删除元素节点文本节点,不可用于特性节点

  [注意]IE浏览器不支持该方法

<div id="test" title='div'>123</div>
<script>
//文本节点
console.log(test.childNodes[0]);//'123'
test.childNodes[0].remove();
console.log(test.childNodes[0]);//undefined //特性节点
console.log(test.attributes.title);//'div'
//报错,remove()方法无法用于删除特性节点
try{test.attributes[0].remove()}catch(e){
console.log('error');
}
//元素节点
console.log(test);
test.remove();
</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 class="list" id="list">
<li class="in">1</li>
<li class="in">2</li>
<li class="in">3</li>
<li class="in">4</li>
<li class="in">5</li>
<li class="in">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);//
//但并没有复制属性
console.log(deepList.index);//undefined
var shallowList = oList.cloneNode();
//浅复制不复制子节点
console.log(shallowList.children.length);//
</script>

深入理解DOM节点操作的更多相关文章

  1. (转载)html dom节点操作(获取/修改/添加或删除)

    DOM 是关于如何获取.修改.添加或删除 HTML 元素的标准,下面为大家介绍下html dom节点操作,感兴趣的朋友可以参考下   HTML DOM 是关于如何获取.修改.添加或删除 HTML 元素 ...

  2. 04-老马jQuery教程-DOM节点操作及位置和大小

    1. jQuery创建DOM标签 1.1 DOM动态创建标签的方法 DOM时代我们通过document的createElement方法动态创建标签.创建标签后,动态的给他添加属性.例如代码: // 动 ...

  3. 第一百六十七节,jQuery,DOM 节点操作,DOM 节点模型操作

    jQuery,DOM 节点操作,DOM 节点模型操作 学习要点: 1.创建节点 2.插入节点 3.包裹节点 4.节点操作 DOM 中有一个非常重要的功能,就是节点模型,也就是 DOM 中的“M”.页面 ...

  4. 前端JavaScript之DOM节点操作

    1.HTML DOM是啥 Document Object Model:定义了访问和操作HTML文档的标准方法,把HTML文档呈现为带有元素,属性和文本的树状结构 2.解析过程 HTML加载完毕,渲染引 ...

  5. Dom节点操作总结

    Dom   一:Dom的概念 Dom的简介:  全称为 document object model  文档对象模型,是操作文档的一整套方法 - 文档 - html,document时一个对象,是dom ...

  6. 深入理解DOM节点类型第五篇——元素节点Element

    × 目录 [1]特征 [2]子节点 [3]特性操作[4]attributes 前面的话 元素节点Element非常常用,是DOM文档树的主要节点:元素节点是html标签元素的DOM化结果.元素节点主要 ...

  7. 深入理解DOM节点类型第四篇——文档片段节点DocumentFragment

    × 目录 [1]特征 [2]作用 前面的话 在所有节点类型中,只有文档片段节点DocumentFragment在文档中没有对应的标记.DOM规定文档片段(document fragment)是一种“轻 ...

  8. 深入理解DOM节点类型第一篇——12种DOM节点类型概述

    × 目录 [1]元素 [2]特性 [3]文本[4]CDATA[5]实体引用[6]实体名称[7]处理指令[8]注释[9]文档[10]文档类型[11]文档片段[12]DTD 前面的话 DOM是javasc ...

  9. 第6章 DOM节点操作

    一.创建节点 为了使页面更加智能化,有时我们想动态的在 html 结构页面添加一个元素标签,那么 在插入之前首先要做的动作就是:创建节点. varbox=$('<div id="box ...

随机推荐

  1. 【AR实验室】mulberryAR : ORBSLAM2+VVSION

    本文转载请注明出处 —— polobymulberry-博客园 0x00 - 前言 mulberryAR是我业余时间弄的一个AR引擎,目前主要支持单目视觉SLAM+3D渲染,并且支持iOS端,但是该引 ...

  2. 理解 .NET Platform Standard

    相关博文:ASP.NET 5 Target framework dnx451 and dnxcore50 .NET Platform Standard:https://github.com/dotne ...

  3. C#委托异步调用

    参考页面: http://www.yuanjiaocheng.net/webapi/mvc-consume-webapi-get.html http://www.yuanjiaocheng.net/w ...

  4. Autofac - MVC/WebApi中的应用

    Autofac前面写了那么多篇, 其实就是为了今天这一篇, Autofac在MVC和WebApi中的应用. 一.目录结构 先看一下我的目录结构吧, 搭了个非常简单的架构, IOC(web), IBLL ...

  5. 【干货分享】流程DEMO-加班与调休

    流程名: 加班.调休  业务描述: 加班: 工作日加班可以申请调休,也可以申请支付加班费.原则上都应申请调休:周末加班原则上申请调休:法定节假日加班支付加班费. 加班申请以半小时为单位. 当月加班不能 ...

  6. BPM配置故事之案例11-操作外部数据源

    小明:可以获取ERP数据了-- 老李:哦,这么快?小伙子,我非常看好你,来来,别急着走,再陪我聊会-- 小明:--您老人家不是又要改流程吧? 老李:没有没有,哎嘿嘿嘿,我们这不都是为公司效率着想嘛,这 ...

  7. 敏捷转型历程 - Sprint3 Planning

    我: Tech Leader 团队:团队成员分布在两个城市,我所在的城市包括我有4个成员,另外一个城市包括SM有7个成员.另外由于我们的BA离职了,我暂代IT 的PO 职位.PM和我在一个城市,但他不 ...

  8. T-SQL字符串相加之后被截断的那点事

    本文出处:http://www.cnblogs.com/wy123/p/6217772.html 字符串自身相加, 虽然赋值给了varchar(max)类型的变量,在某些特殊情况下仍然会被“截断”,这 ...

  9. OpenWrt中开启usb存储和samba服务

    在从官网安装的WNDR3800 15.05.1版本OpenWrt中, 不带usb存储支持以及samba, 需要另外安装 1. 启用usb支持 USB Basic Support https://wik ...

  10. ASP.NET Aries 3.0发布(附带通用API设计及基本教程介绍)

    主要更新: 1:升级处理机制(js请求由同步变更为异步) 2:优化前端JS:包括API和配置方式. 3:增加InputDialog功能. 4:增远远程验证功能. 5:优化权限安全机制. 6:增加一次请 ...