深入理解DOM节点操作
前面的话
一般地,提起操作会想到“增删改查”这四个字,而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节点操作的更多相关文章
- (转载)html dom节点操作(获取/修改/添加或删除)
DOM 是关于如何获取.修改.添加或删除 HTML 元素的标准,下面为大家介绍下html dom节点操作,感兴趣的朋友可以参考下 HTML DOM 是关于如何获取.修改.添加或删除 HTML 元素 ...
- 04-老马jQuery教程-DOM节点操作及位置和大小
1. jQuery创建DOM标签 1.1 DOM动态创建标签的方法 DOM时代我们通过document的createElement方法动态创建标签.创建标签后,动态的给他添加属性.例如代码: // 动 ...
- 第一百六十七节,jQuery,DOM 节点操作,DOM 节点模型操作
jQuery,DOM 节点操作,DOM 节点模型操作 学习要点: 1.创建节点 2.插入节点 3.包裹节点 4.节点操作 DOM 中有一个非常重要的功能,就是节点模型,也就是 DOM 中的“M”.页面 ...
- 前端JavaScript之DOM节点操作
1.HTML DOM是啥 Document Object Model:定义了访问和操作HTML文档的标准方法,把HTML文档呈现为带有元素,属性和文本的树状结构 2.解析过程 HTML加载完毕,渲染引 ...
- Dom节点操作总结
Dom 一:Dom的概念 Dom的简介: 全称为 document object model 文档对象模型,是操作文档的一整套方法 - 文档 - html,document时一个对象,是dom ...
- 深入理解DOM节点类型第五篇——元素节点Element
× 目录 [1]特征 [2]子节点 [3]特性操作[4]attributes 前面的话 元素节点Element非常常用,是DOM文档树的主要节点:元素节点是html标签元素的DOM化结果.元素节点主要 ...
- 深入理解DOM节点类型第四篇——文档片段节点DocumentFragment
× 目录 [1]特征 [2]作用 前面的话 在所有节点类型中,只有文档片段节点DocumentFragment在文档中没有对应的标记.DOM规定文档片段(document fragment)是一种“轻 ...
- 深入理解DOM节点类型第一篇——12种DOM节点类型概述
× 目录 [1]元素 [2]特性 [3]文本[4]CDATA[5]实体引用[6]实体名称[7]处理指令[8]注释[9]文档[10]文档类型[11]文档片段[12]DTD 前面的话 DOM是javasc ...
- 第6章 DOM节点操作
一.创建节点 为了使页面更加智能化,有时我们想动态的在 html 结构页面添加一个元素标签,那么 在插入之前首先要做的动作就是:创建节点. varbox=$('<div id="box ...
随机推荐
- Bringing Whoops Back to Laravel 5
You might be missing the "prettier" Whoops error handler from Laravel 4. If so, here's how ...
- 学习ASP.NET Core, 怎能不了解请求处理管道[3]: 自定义一个服务器感受一下管道是如何监听、接收和响应请求的
我们在<服务器在管道中的"龙头"地位>中对ASP.NET Core默认提供的具有跨平台能力的KestrelServer进行了介绍,为了让读者朋友们对管道中的服务器具有更 ...
- PHP与API讲解(一)
了解API: 在使用与创建自己的API之前我们需要先了解什么是API! API代表应用程序编程接口,而接口指的是一个特定的服务.一个应用程序或者其他程序的公共模块. 理解SOA(面向服务的架构):SO ...
- CSS 3学习——box-sizing和背景
box-sizing 在CSS 2中设置元素的width和height仅仅是设置了元素内容区的宽和高,元素实际的尺寸是margin + border + padding + 内容区. CSS 3(截止 ...
- 代码的坏味道(22)——不完美的库类(Incomplete Library Class)
坏味道--不完美的库类(Incomplete Library Class) 特征 当一个类库已经不能满足实际需要时,你就不得不改变这个库(如果这个库是只读的,那就没辙了). 问题原因 许多编程技术都建 ...
- 代码的坏味道(16)——纯稚的数据类(Data Class)
坏味道--纯稚的数据类(Data Class) 特征 纯稚的数据类(Data Class) 指的是只包含字段和访问它们的getter和setter函数的类.这些仅仅是供其他类使用的数据容器.这些类不包 ...
- BPM助力企业数字化转型
自九十年代末,流程管理开始引入国内,至今已经有20多年的历史了,由最初的部门级应用向企业级应用转变,大家的认知也经历了一系列的发展变化.不同阶段的信息化水平对企业的流程以及BPM平台也提出了不同的需求 ...
- 【开源】专业K线绘制[K线主副图、趋势图、成交量、滚动、放大缩小、MACD、KDJ等)
这是一个iOS项目雅黑深邃的K线的绘制. 实现功能包括K线主副图.趋势图.成交量.滚动.放大缩小.MACD.KDJ,长按显示辅助线等功能 预览图 最后的最后,这是项目的开源地址:https://git ...
- 解决WINDOWS防火墙开启后Ping不通
WINDOWS系统由于安全考虑,当开启防火墙时,默认不允许外主机对其进行ping功能,即别的电脑ping不通本机.别的主机ping不通本机是因为本机的防火墙关闭了ICMP回显功能,只要把这回显功能打开 ...
- 支付宝web支付
过程 1. 用户下单 2. 商户后台产生订单 3. 请求支付宝web支付页面(将订单信息返回给用户---放在form里面---隐藏起来-----并通过脚本自动提交此form到支付宝web支付页) 4. ...