DOM基本操作
节点的类型:
- 元素节点 1
- 属性节点 2
- 文本节点 3
- 注释节点 8
- document 9
- DocumentFragment 11
节点的四个属性:
- nodeName 元素的标签名,以大小写形式表示,只读
- nodeValue Text节点或Comment(注释)节点的文本内容,可读写
- nodeType 该节点的类型,只读
- attribute 节点的属性集合
节点的一个方法: Note.hasChildNodes();
获取节点
document代表整个文档:
- document.getElementByld()通过元素id获取节点
- .getElementsByTagName()通过元素标签获取节点
- getElementsByName();通过元素的name获取节点
- .getElementsByClassName()
- .querySelector//css选择器(在css中怎么选,这里就怎么选),在ie7和ie以下的版本中没有,不是实时的。
- .querySelectorAll()//css选择器,在ie7和ie以下的版本中没有,不是实时的。
基于节点树的遍历(节点指针):
- parenNote –>获取已知节点的父节点(最顶端的parentNode为#docuemnt);
- childNodes –>获取元素的节点列表
- firstChild —>获取元素的首个子节点
- lastChild —>获取元素的最后一个子节点
- nextSibling —>获取已知节点的后一个兄弟节点
- previousSibling —>获取已知节点的前一个兄弟节点
基于元素节点树的遍历(元素节点指针):
- parentElement–>返回当前元素的父元素节点(IE不兼容)
- children —>返回当前元素子节点
- node.children.length === node.childElementCount 返回当前元素节点数。(IE不兼容)
- firstElementChild—>返回第一个孩子节点(IE不兼容)
- lastElementChild—>返回最后一个孩子节点(IE不兼容)
- nextElementSibling —>返回下一个兄弟元素节点。 (IE不兼容)
- previousElementSibling –>返回前一个兄弟元素节点。(IE不兼容)
节点操作:
- 创建节点:
- document.createElement(元素标签)
创建元素节点 - document.createAttribute(元素属性)
创建属性节点 - document.createTextNode(文本文档)
创建文本节点
- document.createElement(元素标签)
eg:
增加或创建一个元素节点:
var div = document.createElement('div');
增加或创建一个文本节点:
var text = document.createTextNode('文本');
增加或创建一个注释节点:
var comment = document.createcomment('注释');
增加或创建一个文档碎片节点:
var document = documentDocumentFragment();
- 插入节点
appenChild(所添加的新节点)
向节点的子节点列表的末端添加新的子节点- insertBefore(a,b)在b之前插入a
在已知子节点前插入一个新的子节点
- insertBefore(a,b)在b之前插入a
替换节点
- replaceChild(要插入的新元素,将被替换的老元素)
将某个子节点替换为另一个
- replaceChild(要插入的新元素,将被替换的老元素)
复制节点
- cloneNode(需要被复制的节点.cloneNode(true/false))
创建指定节点的副本
参数:true:复制当前节点及其所有子节点
false:仅复制当前节点
- cloneNode(需要被复制的节点.cloneNode(true/false))
删除节点
- parent.removeChild(父元素删除子节点)
删除指定的节点 - child.remove(子元素自己删除自己)
删除指定的节点
- parent.removeChild(父元素删除子节点)
属性操作:
- 获取属性
- getAttribute(元素节点.getAttribute(元素属性名))
删除指定节点
- getAttribute(元素节点.getAttribute(元素属性名))
- 设置属性
- setAttritube(元素节点.setAttritube(属性名,属性值))
创建或改变元素节点的属性
- setAttritube(元素节点.setAttritube(属性名,属性值))
eg:div.setAttritube('class','demo');
<div class="demo">...</div>
eg:div.setAttritube('id','only');
<div id = "only" >...</div>
- 删除属性
- removeAttritube(元素节点.removeAttritube(属性名))
删除元素中的指定属性
- removeAttritube(元素节点.removeAttritube(属性名))
eg: div.getAttritube('id');
div.setAttritube('id','only');
//undefined
- 行间属性(统计用户在页面的某一位置点击了多少次):
a.onclick = function() {
console.log(this.getAttribute(‘data-log’));
}
文本操作:
- insertData(offset,string)
从offset指定的位置插入string - appenData(string)
将string插入到文本节点的末尾端 - deleteData(offset,count)
从offset起删除count个字符 - replaceData(off,count,string)
从off将count个字符用string替代 - splitData(offset)
从offset起将文本节点分成两个节点 - substring(offset,count)
返回由offset起的count个节点
练习题:将div下面的元素子节点全部挑出来,放到一个数组里返回,并且不能用child。
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
</head>
<body>
<div>
<div>
<strong>
<span>
<i></i>
</span>
</strong>
</div>
</div>
</body>
<script type="text/javascript">
var div = document.getElementsByTagName('div')[0];
function retElementChild(node) {
var arr = {
length : 0,
push : Array.prototype.push,
splice : Array.prototype.splice
},
child = node.childNodes,
len = child.length;
for(var i = 0;i < len; i++) {
if(child[i].nodeType === 1) {
temp.push(child[i]);
}
}
return temp;
}
</script>
Dom的基本操作:
1.getElementById方法定义在Document.prototype上,即Element节点上不能使用
2.getElementsByName方法定义在HTMLDocument.prototype上,即非HTMLDocument不能使用
3.getElementsByTagName方法定义在Document.prototype和Element.prtotype上
4.HTMLDocument.prototype定义了一些常用的属性,body,head分别指文档中的<body><head>标签
5.Document.prototype上定义了documentElement属性,指代文档的根元素HTML文档,他总是指代<html>元素
6.getElementsByClassName,querySelector,querySelectorAll在Document.prototype,Element.prototype类中均有定义。
所参照的继承关系:
document --> HTMLDocument.prototype --> Document.prototype
练习:
封装函数,返回元素e的第n层祖先元素节点。
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
</head>
<body>
<div>
<b></b>
<span>
<i></i>
</span>
</div>
</body>
<script type="text/javascript">
function retrParent(elem,n) {
while(elem && n) { //当elem向上寻找原型,找到null的时候停止
elem = elem.parentElement;
n -- ;
}
return elem;
}
var i = document.getElementsByTagName('i')[0];
</script>
练习:
编辑函数,封装myChildren功能,解决以前部分浏览器的兼容性问题。(如何区分元素节点和非元素节点)
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
</head>
<body>
<div>
<b></b>
<strong>
<span>
<i></i>
</span>
</strong>
</div>
</body>
<script type="text/javascript">
Element.prototype.mychildren = function() {
var child = this.childNodes; //获取元素的节点列表
var len = child.length;
var arr = []; //容器
for(var i = 0; i < len; i++) {
if(child[i].nodeType == 1) { //该节点的类型,元素节点 -- 1
arr.push(child[i]);
}
}
return arr;
}
var div = document.getElementsByTagName('div')[0];
</script>
意思是想用咱们自己的方法,实现myChildren功能的实现。
思路:获取子节点,从子节点里挑出元素节点,放进新的数组容器里,再返回该数组。
练习:
自己封装hasChildren()方法,不可用children属性
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
</head>
<body>
<div>
<b></b>
<strong>
<span>
<i></i>
</span>
</strong>
</div>
</body>
<script type="text/javascript">
Element.prototype.mychildren = function() {
var child = this.childNodes; //获取元素的节点列表
var len = child.length;
var arr = []; //容器
for(var i = 0; i < len; i++) {
if(child[i].nodeType == 1) { //该节点的类型,元素节点 -- 1
return true;
}
}
return false;
}
var div = document.getElementsByTagName('div')[0];
</script>
练习:
封装函数,返回元素e的第n个兄弟元素节点,n为正,返回后面的兄弟的元素节点;n为负,返回前面的;n为0,返回自己。
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
</head>
<body>
<div>
<span></span>
<p></p>
<strong></strong>
<i></i>
<address></address>
</div>
</body>
<script type="text/javascript">
function retSibling(e,n) { //元素 第n个兄弟节点
while(e && n) {
if(n > 0) {
e = e.nextElementSibling
n--;
}else{
e = e.previousElementSibling;
n++;
}
}
return e;
}
var strong = document.getElementsByTagName('strong')[0];
</script>
nextElementSibling、previousElementSibling兼容性不好,在ie9以下是不兼容的,所以我们优化一下代码:
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
</head>
<body>
<div>
<span></span>
<p></p>
<strong></strong>
<i></i>
<address></address>
</div>
</body>
<script type="text/javascript">
function retSibling(e,n) { //元素 第n个兄弟节点
while(e && n) {
if(n > 0) {
if(0 && e.nextElementSibling) { //找到的元素为真
e = e.nextElementSibling
}else{
for(e = e.mextSibling;e && e.nodeType !=1;e = e.mextSibling); //看标签节点是否找完了,比如n = 3时,<addrss>后面就没有了
}
n--;
}else{
if(e = e.previousElementSibling;){
e = e.previousElementSibling;
}elsa{
for(e= e.previousElementSibling ; e&&e.nodeType !=1; e =e.previousSibling
}
n++;
}
}
return e;
}
var strong = document.getElementsByTagName('strong')[0];
</script>
这样写是非常完整的,如果是ie9以下,会直接跳到else执行,ie9以上直接在最初版本的if里面执行。
练习:
请编写一段JavaScript脚本生成下面这段DOM结构。要求:使用标准的DOM方法或属性。
<div class="example">
<p class="slogan">文本</p>
</div>
提示:div.className可以直接改元素的class,同理,id也可以
<html>
<head>
<title>Dom</title>
</head>
<body>
<div>
<p></p>
<address></address>
</div>
</body>
<script type="text/javascript">
var div = document.createElement('div');
var p = document.createElement('p');
div.setAttribute('class','example');
p.setAttribute('class','slogan');
var text = document.createTextNode('文本');
p.appendChild(text);
div.appendChild(p);
document.body.appendchild(div);
</script>
练习题:
封装函数insertAfter();功能类似insertBefore();
提示:可忽略老版本浏览器,直接在Element.prototype上编程。
<!DOCTYPE html>
<html>
<head>
<title>insertAfter</title>
</head>
<body>
<div>
<i></i>
<b></b>
<span></span>
</div>
</body>
<script type="text/javascript">
Element.prototype.insertAfter = function(targetNode,afterNode) {
var beforeNode = afterNode.nextElementSlibling;
if(beforeNode == null) { //如果刚好在最后一个标签,没办法选中后一个,则直接用appendChild()给它加
this.appendChild(targetNode);
}else{
this.insertBefore(targetNode,beforeNode);
}
var div = document.getElementsByTagName('div')[0];
var b = document.getElementsByTagName('b')[0];
var span = document.getElementsByTagName('span')[0];
var p = document.createElement('p'); //全部选出来,哪个后面加就给那个后面加
</script>
练习题:
将目标节点内部的节点的顺序逆序。
eg: <div><a></a><em></em></div>
<div><em></em><a></a></div>
提示:利用appendChild的剪切的特性。