11. JS DOM
DOM 简介
DOM 获取元素
DOM 操作
DOM 节点(Node)
DOM 应用
练习
一、DOM 简介
-
HTML的标准对象模型
-
HTML 的标准编程接口
-
W3C 标准
-
当页面加载时,浏览器会创建页面的文档对象模型(Document Object Model)
-
HTML DOM 定义了所有 HTML 元素的对象和属性,以及访问它们的方法。
换言之,HTML DOM 是关于如何获取、修改、添加或删除 HTML 元素的标准 -
DOM 将 HTML 文档呈现为带有元素、属性和文本的树结构,即节点树
我们之所以能够对Web页面进行添加、删除、更新、操控元素等等活动,就是因为DOM才得以实现。它定义了一套对象(方法)规则,使得JavaScript可以根据这些规则来进行编程,更像是一个文档API。
DOM结构树:


-
形成原型链:
document--->HTMLDocument.prototype-->Document.prototype-->Node.prototype-->EventTarget.prototype-->Object.prototype-->null
二、DOM 获取元素
每个载入浏览器的 HTML 文档都会成为 Document 对象。
Document 对象使我们可以从脚本中对 HTML 页面中的所有元素进行访问。
提示:Document 对象是 Window 对象的一部分,可通过 window.document 属性对其进行访问。
所谓的 DOM,实际上就是 document,获取元素就是操作 document。
JS 要想操作 HTML 元素,那么首先就必须先找到该元素,通常使用以下几种方法完成。
1. document.getElementById('元素id');
- 通过元素 id 获取节点
定义了一个工具函数,这样您就可以通过一个较短的名字来使用 getElementById() 方法了
function id(x) {
if (typeof x == "string") return document.getElementById(x);
return x;
}
// 上面这个函数接受元素 ID 作为它们的参数。使用前编写 x = id(x) 就可以了。
2. document.getElementsByTagName('元素标签'); ==> 最常用
-
通过元素标签获取节点
-
返回的是带有指定标签名的对象的集合,也就是以数组的形式返回,返回的顺序是他们在文档中的顺序
-
如果把特殊字符串
"*"传递给getElementsByTagName()方法,它将返回文档中所有元素的列表,元素排列的顺序就是它们在文档中的顺序
传递给
getElementsByTagName()方法的字符串可以不区分大小写
3. document.getElementsByName('元素name属性'); ==> 基本不用
-
通过元素的 name 属性获取节点
-
只有部分标签 name 可生效(表单,img,iframe)
-
返回带有指定名称的对象的集合
该方法与
getElementById()方法相似,但是它查询元素的name属性,而不是id属性。
另外,因为一个文档中的name属性可能不唯一(如 HTML 表单中的单选按钮通常具有相同的name属性),所有getElementsByName()方法返回的是元素的数组,而不是一个元素。
<body>
<input name="txt" type="text" value="1">
<input name="txt" type="text" value="2"><br>
<input name="txt" type="text" value="3">
<input name="txt" type="text" value="4"><br>
<input name="txt" type="text" value="5">
<input name="aaa" type="text" value="6">
<script>
//获取所有name值为txt的元素
var oTxt = document.getElementsByName("txt");
//获取元素的个数
alert(oTxt.length); //返回:5
//获取第二个元素的值
alert(oTxt[1].value); //返回:2
</script>
</body>
4. document.getElementsByClassName('class名')
- 查找带有相同类名的所有 HTML 元素的列表
在 Internet Explorer 5,6,7,8 中无效,所以常用 getElementsByTagName
<div class="demo"></div>
<p class = "demo"></p>
<div class="demo">
<span class= "demo"></span>
</div>
var div = document.getElementsByClassName('demo');

object.className = 'className'
-
用于设置或者返回元素的 class 类名
-
该方法可以控制 class 类名,返回元素的 class 属性,作用是可以为网页中某个元素指定一个 className 来更改该元素的外观
- 示例:简单的网页换肤
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>网页换肤</title>
<style>
body{
background:lightgreen;
}
.col1{
background:lightgray;
}
.col2{
background:lightblue;
}
.col3{
background:violet;
}
.col4{
background:pink;
}
.col5{
background:#f93;
}
</style>
</head>
<body id="boy">
点击切换:<input type="button" value="灰色" onclick="gr()">
<input type="button" value="蓝色" onclick="bl()">
<input type="button" value="紫色" onclick="vi()">
<input type="button" value="粉色" onclick="pi()">
<input type="button" value="橘色" onclick="or()">
<script>
var x = document.getElementById('boy');
function gr(){
x.className = 'col1';
}
function bl(){
x.className = 'col2';
}
function vi(){
x.className = 'col3';
}
function pi(){
x.className = 'col4';
}
function or(){
x.className = 'col5';
}
</script>
</body>
</html>

-
设置多个 class 类名相同的元素的样式(效果和 getElementsByClassName 一样)
- 示例:将有序列表中所有 class 属性值为"col"的元素背景颜色设置为绿色
<body>
<ol id="o1">
<li>热点</li>
<li class="col">美食</li>
<li>数码</li>
<li class="col">科技</li>
<li>社会</li>
<li class="col">养生</li>
</ol>
<script>
//通过id获取父元素
var aOl = document.getElementById('o1');
//通过标签名获取父元素下所有子元素
var oLi = aOl.getElementsByTagName('li');
//循环遍历返回的子元素数组
for(var i=0; i<oLi.length; i++){
//如果当前子元素的className等于设置的class属性值,则将其背景设置为绿色
if(oLi[i].className == 'col') oLi[i].style.background = 'green';
}
</script>
</body>
通过 class 属性值获取元素的封装函数
- 解决
getElementsByClassName浏览器兼容问题
<ol id="o1">
<li>热点</li>
<li class="col">美食</li>
<li>数码</li>
<li class="col">科技</li>
<li>社会</li>
<li class="col">养生</li>
</ol>
// 封装函数
function getByClass(oParent,aClass){ //第一个参数为获取的父元素,第二个参数为class属性值。
//如果浏览器支持 会得到一个函数体
if(oParent.getElementsByClassName){
return oParent.getElementsByClassName(aClass);
}
//通过标签名获取父元素下所有子元素。标签名不固定,所以设置为*,便于传入。
var allItems = oParent.getElementsByTagName("*");
//设置空数组备用,最后可以把找到的所有className都存放在里边并返回。
var newArr = [];
//查找每一个元素的 className 看其中是否包含 aClass 参数
for(var i = 0; i < allItems.length; i++){
var arrClass = allItems[i].className.split(" ");
for(var j = 0; j < arrClass.length; j++){
if(arrClass[j]==name){
newArr.push(allItems[i]);
}
}
}
// 最后返回数组
return newArr;
}
//封装函数的使用:
//先通过id获取父元素
var aOl = document.getElementById('o1');
//再调用封装好的函数传入参数,获取的父元素,子元素的class属性值
//如果父元素是文档就传入 document
var oCol = getByClass(aOl,'col');
//最后循环遍历,设置样式
for(var i=0; i<oCol.length; i++){
oCol[i].style.background = 'green';
}
5. querySelector(),querySelectorAll()
querySelector() 返回文档中匹配指定 CSS 选择器的一个元素
参数:CSS 选择器, 必须。指定一个或多个匹配元素的 CSS 选择器。 可以 使用它们的 id, 类, 类型, 属性, 属性值等来选取元素。对于多个选择器,使用逗号隔开,返回一个匹配的元素。
querySelector() 方法仅仅返回匹配指定选择器的第一个元素。如果你需要返回所有的元素,请使用 querySelectorAll() 方法替代。querySelector 返回的是单个 DOM 元素;querySelectorAll 返回的是 NodeList.
querySelector 和 querySelectorAll IE8+浏览器支持。
<div class="demo">
<span class= "demo">a</span>
<i class = "a">123</i>
<div class = "inner">
<strong></strong>
</div>
</div>
var strong= document.querySelector('div.demo div.inner strong'); // 选择 strong 标签
queryselect()和queryselectAll()缺点:
-
它不是实时的,它只是保存了选择出来的那些元素的副本,当它们动态改变的时候,用queryselect()和queryselectAll()选出来的还是原来的,不会跟着改变。
三、DOM 操作
- 获取到 HTML 元素之后,就可以进行相应的操作。
1. 改变HTML
-
修改 HTML 内容的最简单的方法时使用
innerHTML属性。innerHTML 顾名思义,inner 就是内部的,既然是 HTML,那么就可以给里边放 HTML。该属性可用于获取和替换 HTML 元素的内容。 -
document.getElementById(id).innerHTML = new HTML
//<p id="intro">Hello World!</p>
var txt = document.getElementById("intro").innerHTML; //获取
document.write(txt);
/*
Hello World!
Hello World!
*/
------------------------------------------
//<p id="p-id">...</p>
var p = document.getElementById('p-id');
// 设置文本为abc:
p.innerHTML = 'ABC'; // ABC
// 设置HTML:
p.innerHTML = 'ABC <span style="color:red">RED</span> XYZ';
// <p>...</p>的内部结构已修改
// ABC RED XYZ
2. 操作元素属性
(1) 获取属性:getAttribute()
-
语法:元素节点.getAttribute(元素属性名)
-
获取元素节点中指定属性的属性值
(2) 设置属性:setAttribute()
-
语法:元素节点.setAttribute(属性名,属性值)
-
添加一个新属性并指定值,或者把一个现有的属性设定为指定的值
(3) 删除属性:removeAttribute()
-
语法:元素节点.removeAttribute(属性名)
-
删除元素中的指定属性
<input id="txt1" type="text">
<input id="btn1" type="button" value="按钮">
var oTxt = document.getElementById('txt1');
var oBtn = document.getElementById('btn1');
//获取按钮value属性的值
var a = oBtn.getAttribute('value');
console.log(a); //按钮
oBtn.onclick = function (){
//操作元素属性有三种方法:
//第一种方法
//oTxt.value='请输入文字';
//第二种方法
//oTxt['value']='请输入文字';
//第三种方法
//修改文本框value属性的值
oTxt.setAttribute('value','请输入文字');
//删除按钮type属性
oBtn.removeAttribute('type');
//按钮删除后默认变成文本框,原来的 value 值变成文本框中的文本
};
3. 改变CSS
-
document.getElementById(id).style.样式名 = new style -
DOM 节点的 style 属性对应所有的 CSS,可以直接获取或设置。
-
因为CSS允许
font-size这样的名称,但它并非 JS 有效的属性名,所以需要在 JS 中改写为驼峰式命名fontSize
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JavaScript实例</title>
<style>
#div1{
height:400px;
width:600px;
border:1px solid black;
padding:5px;
}
p{
line-height:18px;
text-indent:2em;
}
</style>
</head>
<body>
<h2>HTML DOM</h2>
<div id="div1">
<h3>JS可以使网页添加动态效果并实现与用户交互的功能。</h3>
<p>1. JS能够改变页面中所有的 HTML 元素。</p>
<p>2. JS能够改变页面中所有的 HTML 属性。</p>
<p>3. JS能够改变页面中所有的 HTML 元素的CSS样式。</p>
</div>
<input type="button" value="改变颜色" onclick="color()">
<input type="button" value="改变宽高" onclick="hig()">
<input type="button" value="隐藏内容" onclick="none()">
<input type="button" value="显示内容" onclick="block()">
<input type="button" value="取消设置" onclick="cancel()">
<script>
var oDiv = document.getElementById('div1');
function color(){
oDiv.style.color = 'white';
oDiv.style.fontFamily = 'Microsoft YaHei';
oDiv.style.backgroundColor = 'green';
}
function hig(){
oDiv.style.width = '400px';
oDiv.style.height = '300px';
oDiv.style.border = '5px solid #ccc';
}
function none(){
oDiv.style.display = 'none';
}
function block(){
oDiv.style.display = 'block';
}
//取消设置
function cancel(){
var clean = confirm('确定取消所有设置?');
if(clean == true){
oDiv.removeAttribute('style');
}
}
</script>
</body>
</html>
.style.%E6%A0%B7%E5%BC%8F%E5%90%8D%20%3D%20new%20style.gif)
4. 对事件做出响应
<!--全选和反选,输入对应的序号选中-->
<form id="list">
请选择你的业余爱好:<br>
1. 音乐<input type="checkbox" name="love" id="like1">
2. 阅读<input type="checkbox" name="love" id="like2">
3. 游泳<input type="checkbox" name="love" id="like3">
4. 篮球<input type="checkbox" name="love" id="like4">
5. 足球<input type="checkbox" name="love" id="like5">
6. 散步<input type="checkbox" name="love" id="like6">
7. 泡吧<input type="checkbox" name="love" id="like7">
8. 逛街<input type="checkbox" name="love" id="like8"><br>
<input type="button" value = "全选" onclick="optAll()">
<input type="button" value = "反选" onclick="noAll()">
<p>输入1-8序号选择,每次只可以选择一项:</p>
<input id="txt1" type="text">
<input id="btn1" type="button" value="确定">
</form>
//通过获取标签名设置全选
var oList = document.getElementById('list');
var aCheck = oList.getElementsByTagName('input');
function optAll(){
for(var i=0; i<aCheck.length; i++){
if(aCheck[i].type == 'checkbox'){
aCheck[i].checked = true;
}
}
}
//通过获取设置的name属性值设置反选
var aLove = document.getElementsByName('love');
function noAll(){
for(var i=0; i<aLove.length; i++){
if(aLove[i].type == 'checkbox'){
aLove[i].checked = false;
}
}
}
var oBtn = document.getElementById('btn1');
//给获取的按钮添加点击事件
oBtn.onclick = function (){
noAll(); // 清空选项
//获取文本框输入的值
var oTxt = document.getElementById("txt1").value;
//定义的复选框id值为like1-8。括号中进行的是字符串连接,id+输入到文本框的值=该元素的id值
var oLike = document.getElementById('like' + oTxt);
oLike.checked = true;
}

四、DOM 节点(Node)

-
HTML DOM 将 HTML 文档视作树结构
-
HTML 文档可以说是由节点构成的集合,常见的 DOM 节点有三种,即元素节点、属性节点和文本节点。
-
元素节点就是 HTML 标签,标签的属性就是属性节点,文本节点就是页面可以浏览的内容。
-
在文档对象模型中,每一个节点都是一个对象,DOM 节点有三个重要的属性:节点的名称,节点的值和节点的类型。
节点父、子和同胞
节点树中的节点彼此拥有层级关系。
父(parent)、子(child)和同胞(sibling)等术语用于描述这些关系。父节点拥有子节点,同级的子节点被称为同胞(兄弟或姐妹)。
-
在节点树中,顶端节点被称为根(root)
-
每个节点都有父节点、除了根(它没有父节点)
-
一个节点可拥有任意数量的子节点
-
同胞是拥有相同父节点的节点
下面的图片展示了节点树的一部分,以及节点之间的关系:

操作一个DOM节点实际上就是这么几个操作:
- 更新:更新该DOM节点的内容,相当于更新了该DOM节点表示的HTML的内容;
- 遍历:遍历该DOM节点下的子节点,以便进行进一步操作;
- 添加:在该DOM节点下新增一个子节点,相当于动态增加了一个HTML节点;
- 删除:将该节点从HTML中删除,相当于删掉了该DOM节点的内容以及它包含的所有子节点。
1. DOM 节点属性
(1) nodeName:节点的名称
-
nodeName 属性返回节点的名称
-
元素节点的名称与标签名相同(大写),属性节点的名称是属性的名称,文本节点的名称永远都是 #text,文档节点的名称永远都是 #document。
-
注释:nodeName 始终包含 HTML 元素的大写字母标签名
(2) nodeValue:节点的值
-
nodeValue 属性返回节点的值。
-
元素节点的值是 undegined 或 null,属性节点的值是属性的值,文本节点的值是文本自身。
(3) nodeType:节点的类型
- nodeType 属性返回节点的类型。
| 节点类型 | 说明 | 值 |
|---|---|---|
| 元素节点 | 每一个HTML标签都是一个元素节点,如 <div> 、 <p>、<ul> 等 | 1 |
| 属性节点 | 元素节点(HTML标签)的属性,如 id 、class 、name 等。 | 2 |
| 文本节点 | 元素节点或属性节点中的文本内容。 | 3 |
| 注释节点 | 表示文档注释,形式为。 | 8 |
| 文档节点 | 表示整个文档(DOM 树的根节点,即 document )。 | 9 |
<body>
<ul>
<li>JS</li>
<li>DOM</li>
</ul>
<script>
var nodes = document.getElementsByTagName('li');
for(var i=0; i<nodes.length; i++){
document.write('第' + (i+1) + '个节点的名称是' + nodes[i].nodeName + '<br>');
document.write('第' + (i+1) + '个节点的值是' + nodes[i].nodeValue + '<br>');
document.write('第' + (i+1) + '个节点的类型是' + nodes[i].nodeType + '<br>');
document.write('<br>');
}
/*
返回:
第1个节点的名称是LI
第1个节点的值是null
第1个节点的类型是1
第2个节点的名称是LI
第2个节点的值是null
第2个节点的类型是1
*/
</script>
</body>
(4) attributes:Element节点的属性集合
<div id='only' class = 'demo'></div> // div 有两个属性 id='only' 和 class = 'demo'
div.attributes // {0:id,1:class,length:2} 类数组
div.attributes[0] // id='only'
div.attributes[0].nodeType // 2 属性节点
节点的一个方法:Node.hasChildNodes()
- 查看元素是否有子节点
<div id='only' class = 'demo'></div> // div.hasChildNodes() --> flase
<div id='only' class = 'demo'> </div> // div.hasChildNodes() --> true 有个文本节点
JS 中函数可以嵌套使用,有父函数有子函数,HTML 标签也可以嵌套使用,那么就说明存在着各种不同的节点关系,比如父节点、子节点和兄弟节点。为了方便操作,DOM定义了一些节点的公共属性。
2. 遍历元素节点树
children 使用率最高
(1) 子节点:
childNodes属性返回节点的子节点集合,可使用length属性返回子节点的数量,然后就可以和数组一样获取需要的信息。
<body>
<ul id="u1">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<!--<ul id="u1"> 第1个节点(文本节点) -->
<!-- <li>第2个节点(元素节点)</li> 第3个节点(文本节点)-->
<!-- <li>第4个节点(元素节点)</li> 第5个节点(文本节点)-->
<!-- <li>第6个节点(元素节点)</li> 第7个节点(文本节点)-->
<!-- <li>第8个节点(元素节点)</li> 第9个节点(文本节点)-->
<!-- <li>第10个节点(元素节点)</li> 第11个节点(文本节点)-->
<!--</ul>-->
<script>
var oUl = document.getElementById('u1');
alert(oUl.childNodes.length);
</script>
</body>
因为通过 childNodes 属性返回的子节点集合,不仅包括元素节点,而且还包括文本节点,浏览器会将标签之间的空白默认为文本节点,如果在空白处输入文字,就会显示在页面上,这就造成了不必要的麻烦。
所以建议使用 `children` 属性,该属性只返回元素节点,不包括文本节点,并且不包括注释节点。
<body>
<ul id="u1">
<li>
我是个文本节点
<span>我是span元素。</span>
</li>
<li></li> <!-- 注释 -->
<li></li>
<li></li>
<li></li>
</ul>
<script>
var oUl = document.getElementById('u1');
alert(oUl.children.length); // ul 下有 5 个 li 元素,返回子节点个数为 5
</script>
</body>
children属性要比childNodes属性好用太多了,只返回元素的子节点,还不包括孙子辈节点。
注:IE6 到 IE8 完全支持 children 属性,但是,返回元素节点和注释节点,IE9 以上版本只返回元素节点。
(2) 首尾子节点:
-
firstElementChild属性返回children数组的第一个节点node.firstElementChild==>element.children[0]
-
lastElementChild属性返回children数组的最后一个节点node.lastElementChild==>element.children[element.children.length-1]
IE6/7/8中不支持firstElementChild属性,可以使用
children[i]属性
<body>
<div style="border:2px solid green" id="div1">
空白节点
<p>JS</p>
<div>DOM</div>
<h3>jQuery</h3>
</div>
<script>
var x = document.getElementById('div1');
document.write('第一个节点的名称:' + x.firstElementChild.nodeName + '<br>');
//返回:第一个子节点的名称:P
document.write('最后一个节点的名称:' + x.lastElementChild.nodeName)
//返回:最后一个子节点的名称:H3
</script>
</body>
(3) 父节点:
-
parentNode属性用于获取指定节点的父节点。 -
最顶端的
parentNode为#document -
注意:父节点只能有一个。通过使用两个获取父节点,可获取祖节点
实例:点击子节点,隐藏父节点
<ul id="u1">
<li>aaa <a href="javascript:;">点击隐藏</a></li>
<li>bbb <a href="javascript:;">点击隐藏</a></li>
<li>ccc <a href="javascript:;">点击隐藏</a></li>
<li>ddd <a href="javascript:;">点击隐藏</a></li>
<li>eee <a href="javascript:;">点击隐藏</a></li>
</ul>
var oUl = document.getElementById('u1');
//查看ul元素的父节点
alert(oUl.parentNode); //返回:[object HTMLBodyElement]
//通过标签名获取所有的a元素
var aA = oUl.getElementsByTagName('a');
for(var i=0; i<aA.length; i++){
aA[i].onclick = function (){ // 为每个按钮设置点击事件
//设置当前节点的父节点为隐藏
this.parentNode.style.display = 'none';
};
}

(4) 兄弟节点:
-
nextElementSibling属性返回同一树层级中某个节点之后紧跟的节点element.nextElementSibling
-
previousElementSibling属性返回同一树层级中某个节点之前紧跟的节点element.previousElementSibling
IE6/7/8中不支持可以使用
children[i]属性
实例:获取 li 元素节点的兄弟节点
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JS</li>
</ul>
var aLi = document.getElementsByTagName('li');
//获取第二个子节点之后紧跟的节点
var x = aLi[1].nextElementSibling;
alert(x.innerHTML); //返回:JS
//获取第二个子节点之前紧跟的节点
var y = aLi[1].previousElementSibling;
alert(y.innerHTML); //返回:HTML
五、DOM 应用
DOM 最实际的应用就是可以通过 JS 创建、插入和删除节点
1. 创建节点
-
createElement()方法可创建元素节点document.createElement(tagName)
实例:创建并添加 li 元素
<input id="txt1" type="text"value="">
<input id="btn1" type="button"value="创建li">
<ul id="u1"></ul>
var oBtn = document.getElementById('btn1');
var oUl = document.getElementById('u1');
var oTxt = document.getElementById('txt1');
//文本框输入提示
oTxt.placeholder = '请输入文字创建li元素';
oBtn.onclick = function (){
//创建li元素
var oLi = document.createElement('li');
//创建的li元素的HTML=文本框输入的值
oLi.innerHTML = oTxt.value;
//插入到oUl父级下,作为子节点,在每个创建的li末尾插入新创建的li元素
oUl.appendChild(oLi);
//父级.appendCild(子节点);
};

2. 插入节点
-
appendChild()方法可在指定节点的末尾插入一个新的子节点,每次都向末尾添加父级.appendChild(new node)
-
insertBefore()方法可在已有的子节点前插入一个新的子节点父级.insertBefore(插入的新子节点, 原有节点)
实例:创建并添加 li 元素,每个新创建的 li 元素都插入到之前插入的 li 元素之前
<input id="txt1" type="text" value="">
<input id="btn1" type="button" value="创建li">
<ul id="u1"></ul>
var oBtn = document.getElementById('btn1');
var oUl = document.getElementById('u1');
var oTxt = document.getElementById('txt1');
oBtn.onclick = function (){
//创建li元素
var oLi = document.createElement('li');
//获取所有li元素
var aLi = oUl.getElementsByTagName('li');
oLi.innerHTML = oTxt.value;
//这里需要注意:页面中本没有li元素,li元素是通过JS创建的
//所以第一个li元素应该添加到父级下最后一个子节点
//然后基于这个节点,将之后再插入的子节点插入到上一个节点之前
//如果li元素本来不存在,则执行else,在父级插入一个子节点。
//如果li元素的个数>0,说明已经创建了,则插入到这个子节点之前。
if(aLi.length>0){
oUl.insertBefore(oLi,aLi[0]);
}
else{
oUl.appendChild(oLi);
}
};

3. 删除节点
-
removeChild()方法用于删除一个节点父级.removeChild(要删除的子节点)
实例:简单的表格添加和删除
var oTab = document.getElementById('tab1');
var oName = document.getElementById('user');
var oAge = document.getElementById('age');
var oBtn = document.getElementById('btn1');
//设置添加的ID项的值
var id = oTab.tBodies[0].rows.length+1;
oBtn.onclick = function (){
//创建一个tr
var oTr = document.createElement('tr');
//创建第一个td(ID项)
var oTd = document.createElement('td');
//获取ID,已经删除的ID号,不能再重用。
oTd.innerHTML = id++;
//将创建的td放入创建的tr中
oTr.appendChild(oTd);
//创建第二个td(姓名项)
var oTd = document.createElement('td');
oTd.innerHTML = oName.value;
oTr.appendChild(oTd);
//创建第三个td(年龄项)
var oTd = document.createElement('td');
oTd.innerHTML = oAge.value;
oTr.appendChild(oTd);
//创建第四个td(操作项)
var oTd = document.createElement('td');
oTd.innerHTML = '<a href="javascript:;">删除</a>';
oTr.appendChild(oTd);
oTd.getElementsByTagName('a')[0].onclick = function (){
//删除整行
oTab.tBodies[0].removeChild(this.parentNode.parentNode);
};
//将创建好的tr放入tbody中
oTab.tBodies[0].appendChild(oTr);
};
姓名:<input id="user"type="text">
年龄:<input id="age"type="text">
<input id="btn1" type="button" value="添加">
<table id="tab1" border="1" width="500px">
<caption>员工表</caption>
<thead>
<tr>
<th>ID</th>
<th>姓名</th>
<th>年龄</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>小白</td>
<td>27</td>
<td></td>
</tr>
<tr>
<td>2</td>
<td>小明</td>
<td>25</td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>小红</td>
<td>21</td>
<td></td>
</tr>
<tr>
<td>4</td>
<td>张三</td>
<td>29</td>
<td></td>
</tr>
<tr>
<td>5</td>
<td>李四</td>
<td>35</td>
<td></td>
</tr>
</tbody>
</table>
4. 替换节点和创建文本节点
-
replaceChild()方法可用于替换元素节点。node.replaceChild (用于替换的节点, 原有节点)
-
createTextNode()方法可创建新的文本节点,返回新创建的 Text 节点document.createTextNode(txt)
-
这两种方法平时几乎用不到,但还是需要了解
六、练习
(1) 封装函数,返回元素e的第n层祖先元素节点
function retParent(elem, n){
while(elem && n){ // 第 n 层就是循环几次,n = 0 时为 flase ,不再循环。
// 因为求祖先元素节点最终时返回 null ,当 n = 6 的时候返回的是 elem 返回的是 null ,
// 条件中的并且关系就不成立了,那后面 n = 7,8.... 返回的都是最后的 null
elem = elem.parentElement;
n--;
}
return elem;
}
var i = document.getElementsByTagName('i')[0]; // 选取元素 e
(2) 在原型链上编辑函数,封装myChildren功能,解决以前部分浏览器不兼容的问题
<div>
<strong>
<span>
<i></i>
</span>
<strong>123</strong>
<img src="" alt="">
</strong>
<div></div>
</div>
var div = document.getElementsByTagName('div')[0];
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){
arr.push(child[i]);
}
}
return arr;
}
console.log(div.myChildren()); //Array [ strong, div ]
(3) 封装一个自己的myHasChildren方法,不可用children属性
Element.prototype.myHasChildren = function () {
var child = this.childNodes;
var len = child.length;
for(var i = 0; i < len; i++){
if(child[i].nodeType === 1){
return true;
}
}
return false;
}
var div = document.getElementsByTagName('div')[0];
console.log(div.myHasChildren());//true
(4) 封装函数,返回元素e的第n个兄弟元素节点;n为正,返回后面的兄弟元素节点;n为负,返回前面的兄弟元素节点;n为0,返回自己。
function retSibling(e, n){
while(e && n){ // n = 0 ,e = null 临界点
if(n > 0){
e = e.nextElementSibling;
n--;
}else{
e = e.previousElementSibling;
n++;
}
}
return e;
-------------------------------------------------------
//解决nextElementSibling在IE里面不兼容的问题:
function retSibling(e, n){
while(e && n){
if(n > 0){
if(e.nextElementSibling){ // ie9 以上会执行
e = e.nextElementSibling;
}else{ //ie9 以下执行
for(e = e.nextSibling; e && e.nodeType != 1; e = e.nextSibling);
// e 最后一个节点是文本节点,它的后面没有兄弟节点了这时 e.nextSibling 就是 null
// 再往后 null.nextSibling 就会报错,所以 e && e.nodeType != 1 都需要满足
}
n--;
}else{
if(e.previousElementSibling){
e = e.previousElementSibling;
}else{
for(e = e.previousSibling; e && e.nodeType != 1; e = e.previousSibling);
}
n++;
}
}
return e;
}
(5) 不用children方法遍历元素直接子节点
<div>
<i></i>
<strong></strong>
<span></span>
<div>
<img src="" alt="">
</div>
</div>
var div = document.getElementsByTagName('div')[0];
function retElementchild(node) {
var temp = {
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;
}
console.log(retElementchild(div));
//Object { 0: i, 1: strong, 2: span, 3: div, length: 4, push: push(), splice: splice() }
(6) 封装函数 insertAfter() 类似于 insertBefore()
<div>
<i></i>
<strong></strong>
<span></span>
<div>
<img src="" alt="">
</div>
</div>
-------------------------------结果如下
<div>
<i></i>
<strong></strong>
<span></span>
<p></p>
<div>
<img src="" alt="">
</div>
</div>
var div = document.getElementsByTagName('div')[0];
var span = document.getElementsByTagName('span')[0];
var p = document.createElement('p');
Element.prototype.insertAfter = function(targetNode,OriginNode) {
var afterS=OriginNode.nextElementSibling;
if (afterS==null) {
this.appendChild(targetNode);
}else{
this.insertBefore(targetNode,afterS);
}
}
div.insertAfter(p,span);
(7) 将目标节点内的节点顺序逆序
<div>
<i></i>
<strong></strong>
<span></span>
</div>
var div = document.getElementsByTagName('div')[0];
function reverse(a) {
for (var i =a.children.length-2; i >=0; i--) {
a.appendChild(a.children[i]);
}
return a.children;
}
console.log(reverse(div));//HTMLCollection(3) [ span, strong, i ]

浙公网安备 33010602011771号