JavaScript DOM
BOM是浏览器对象模型
DOM是文档对象模型动态HTML
节点层次
DOM 描绘了一个层次化的节点树,下面的代码就是我们平时所见到的最基本的层次结构
<html> <head> <title>标题</title> </head> <body> <ui> <a>a</a> <a>b</a> </ui> </body> </html>
注:<html>上面其实还有一个Document,一般隐藏了
Node类型
Node 接口定义了12 个数值常量以表示每个节点的类型,除了IE之外,其他浏览器都可以访问到这些类型,详见下表:
常量名 | 说明 | nodeType 值 |
ELEMENT_NODE | 元素 | 1 |
ATTRIBUTE_NODE | 属性 | 2 |
TEXT_NODE | 文本 | 3 |
CDATA_SECTION_NODE | CDATA | 4 |
ENTITY_REFERENCE_NODE | 实体参考 | 5 |
ENTITY_NODE | 实体 | 6 |
PROCESSING_INSTRUCETION_NODE | 处理指令 | 7 |
COMMENT_NODE | 注释 | 8 |
DOCUMENT_NODE | 文档根 | 9 |
DOCUMENT_TYPE_NODE | doctype | 10 |
DOCUMENT_FRAGMENT_NODE | 文档片段 | 11 |
NOTATION_NODE | 符号 | 12 |
例如,Node.ELEMENT_NODE是元素节点类型,Node.TEXT_NODE是元素文本类型
我们可以通过Node.ELEMENT_NODE与someNode.nodeType相比较,如果二者相等,那么就意味着是一个元素。
节点关系
我们这里可以引用上一节所用的那个基本层次的代码,在HTML中,我们可以将<body>元素看成是<html>的子元素,同时<html>也就是<body>的父元素,对于<head>而言,就是<body>的同胞元素,他们都是<html>的子元素。
对于nodeName,nodeType,nodeValue而言,我们可以用下面的表来表示
节点类型 | nodeName | nodeType | nodeValue |
元素 | 元素名称 | 1 | null |
属性 | 属性名称 | 2 | 属性值 |
文本 | #text | 3 | 文本内容(不包含html) |
这里someNode.nodeName代表着someNode的名字,someNode.nodeValue则代表着someNode的内容或者属性
节点属性
节点的层次结构可以划分为:父节点与子节点、兄弟节点这两种。当我们获取其中一个元素节点的时候,就可以使用层次节点属性来获取它相关层次的节点。层次节点的属性由下表所示:
属性 | 说明 |
childNodes | 获取当前元素节点的所有子节点 |
firstChild | 获取当前元素节点的第一个子节点 |
lastChild | 获取当前元素节点的最后一个子节点 |
ownerDocument | 获取该节点的文档根节点,相当与document |
parentNode | 获取当前节点的父节点 |
previousSibling | 获取当前节点的前一个同级节点 |
nextSibling | 获取当前节点的后一个同级节点 |
attributes | 获取当前元素节点的所有属性节点集合 |
下面我们举几个例子来说明:
var box = document.getElementById('box'); //获取一个元素节点
box.childNodes.length; //获取这个元素节点的所有子节点的数量box.childNodes[0]; //获取第一个子节点对象
box.firstChild.nodeValue; //获取第一个子节点的文本内容
box.lastChild.nodeValue; //获取最后一个子节点的文本内容
box.parentNode.nodeName; //获取父节点的标签名
box.lastChild.previousSibling; //获取前一个同级节点
box.firstChild.nextSibling; //获取后一个同级节点
.....
操作节点
因为关系指针都是只读的,所以DOM也提供了一些操作节点的方法,所以我们单单不仅是查找节点,还可以创建节点、复制节点、插入节点、删除节点和替换节点,具体的方法可以见下表:
方法 | 说明 |
write() | 这个方法可以把任意字符串插入到文档中 |
createElement() | 创建一个元素节点 |
appendChild() | 将新节点追加到子节点列表的末尾 |
createTextNode() | 创建一个文件节点 |
insertBefore() | 将新节点插入在前面 |
repalceChild() | 将新节点替换旧节点 |
cloneNode() | 复制节点 |
removeChild() | 移除节点 |
我们可以这样使用: '节点.方法(内容)'来操作,比如
(这里用的document下面会详细讲到)
write()
document.write('<p>随便写点什么</p>')'; //将“随便写点什么”插入到文档中
createElement()
document.createElement('p'); //创建一个元素节点
appendChild()
var box = document.getElementById('box'); //获取某一个元素节点
var p = document.createElement('p'); //创建一个新元素节点<p>
box.appendChild(p); //把新元素节点<p>添加子节点末尾
createTextNode()
var text = document.createTextNode('段落'); //创建一个文本节点
p.appendChild(text); //将文本节点添加到子节点末尾
insertBefore()
box.parentNode.insertBefore(p, box); //在<div>(box)之前创建一个节点
repalceChild()
box.parentNode.replaceChild(p,box); //把<div>(box)换成了<p>
cloneNode()
var box = document.getElementById('box');
var clone = box.firstChild.cloneNode(true); //获取第一个子节点,true 表示复制内容
box.appendChild(clone); //添加到子节点列表末尾
removeChild()
box.parentNode.removeChild(box); //删除指定节点感
Document类型
javascript通过Document类型表示文档,在浏览器中,Document是HTMLDocument的一个实例,表示整个HTML页面。而且Document对象是window对象的一个属性,所以我们也可以将它作为全部对象来访问。Document节点具有下列的特征:
nodeType的值为9;
nodeName的值为“#document”;
nodeValue的值为null;
parentNode的值为null;
ownerDocument的值为null;
其实我们可以把document理解为我们所看见的整个HTML页面,document.?,这里的?就是我们所要获取的信息,这个信息可以是属性,也可以是对象的集合或者我们所指的内容,比如:
document.title; //获取和设置<title>标签的值 document.URL; //获取URL 路径 document.domain; //获取域名,服务器端 document.referrer; //获取上一个URL,服务器端 document.anchors; //获取文档中带name 属性的<a>元素集合 document.links; //获取文档中带href 属性的<a>元素集合 document.applets; //获取文档中<applet>元素集合,已不用 document.forms; //获取文档中<form>元素集合 document.images; //获取文档中<img>元素集合
......
Element类型
除了Document之外,Element类型就算是WEB编程中最常用的类型了,Element类型用于表现HTML元素,提供了元素的标签名,子节点以及特征的访问,Element节点具有下列的特征:
nodeType的值为1;
nodeName的值为元素的标签名;
nodeValue的值为null;
parentNode的值可能是Document或者Element;
其元素对应的类型表在《JavaScript高级程序设计》P263
Text类型
Text 类型用于表现文本节点类型,其包含的是可以照字面解释的纯文本内容,Text节点具有下列的特征:
nodeType的值为3;
nodeName的值为“#text”;
nodeValue的值为节点所包含的文本;
parentNode是一个Element;
我们可以用appendChild()创建文本节点,这个在操作节点中讲过。
box.normalize(); //将上面的文本合并成一个节点
box.firstChild.splitText(i); //从上面文本字节的第i个开始分离一个节点
当然,Text 还提供了一些别的DOM 操作的方法:
var box = document.getElementById('box');
box.firstChild.deleteData(0,2); //删除从0 位置的2 个字符
box.firstChild.insertData(0,'Hello.'); //从0 位置添加指定字符
box.firstChild.replaceData(0,2,'Miss'); //从0 位置替换掉2 个指定字符
box.firstChild.substringData(0,2); //从0 位置获取2 个字符,直接输出
alert(box.firstChild.nodeValue); //输出结果
Comment类型
注释在DOM中是通过Comment类型来表示的,Comment节点具有如下特征:
nodeType的值为8;
nodeName的值为“#comment”;
nodeValue的值是注释的内容;
parentNode的值可能是Document或者Element;
我们可以通过date或者nodeValue属性获取注释的内容:
<div id="my"><!--hello--></div>
这里注释点是<div>的一个子节点,我们可以这样访问:
var box = document.getElementById('my');
var comment=box.firstChild;
alert(comment.date);//跳出“hello”,这里也可以用alert(comment.nodeValue)
我们也可以使用document.createComment()来传递或者替换注释
var div = document.getElementById("myDiv");
var comment = document.createComment("替换了注释")
alert(comment.data);//跳出“替换了注释”
Attr 类型
Attr 类型表示DOM中元素的特性,Attr具有以下特性:
nodeType的值为2;
nodeName的值是特征的名称;
nodeValue的值是特征的值;
parentNode的值为null;
我们可以使用createAttribute()传入特征名称,并创建新的节点:
function assignAttribute(){
var element = document.getElementById("myDiv");
var attr = document.createAttribute("align");
attr.value = "left";
element.setAttributeNode(attr);
alert(element.attributes["align"].value); //"left"
alert(element.getAttributeNode("align").value); //"left"
alert(element.getAttribute("align")); //"left"
}
DOM操作技术
动态脚本和动态样式一般是我们平时所调用的JavaScript外部文件,这里就不讲了
操作表格
首先我们可以用HTML创建表格:
<table border ="1" width="300"> <caption>人员表</caption> <thead> <tr> <th>姓名</th> <th>性别</th> <th>年龄</th> </tr> </thead> <tbody> <tr> <td>张三</td> <td>男</td> <td>20</td> </tr> <tr> <td>李四</td> <td>女</td> <td>22</td> </tr> </tbody> <tfoot> <tr> <td colspan ="3">合计:N</td> </tr> </tfoot> </table>
注:thead、tfoot、caption标签在一个表格中只能有一个
我们也可以使用核心DOM方法来创建这些元素:
//创建table
var table = document.createElement('table');
table.border = 1;
table.width = 300;
//创建caption
var caption = document.createElement('caption');
table.appendChild(caption);
caption.appendChild(document.createTextNode('人员表'));
//创建thead
var thead = document.createElement('thead');
table.appendChild(thead);
var tr = document.createElement('tr');
thead.appendChild(tr);
var th1 = document.createElement('th');
var th2 = document.createElement('th');
var th3 = document.createElement('th');
tr.appendChild(th1);
th1.appendChild(document.createTextNode('姓名'));
tr.appendChild(th2);
th2.appendChild(document.createTextNode('年龄'));
//将表格添加到文档主题中
document.body.appendChild(table);
这种方法又乱又长,不太好,所以有了HTML DOM,它有一些属性和方法:
属性或方法 | 说明 |
caption | 保存着<caption>元素的引用 |
tBodies | 保存着<tbody>元素的HTMLCollection 集合 |
tFoot | 保存着对<tfoot>元素的引用 |
tHead | 保存着对<thead>元素的引用 |
rows | 保存着对<tr> 元素的HTMLCollection 集合 |
createTHead() | 创建<thead>元素,并返回引用 |
createTFoot() | 创建<tfoot>元素,并返回引用 |
createCaption() | 创建<caption>元素,并返回引用 |
deleteTHead() | 删除<thead>元素 |
deleteTFoot() | 删除<tfoot>元素 |
deleteCaption() | 删除<caption>元素 |
deleteRow(pos) | 删除指定的行 |
insertRow(pos) | 向rows 集合中的指定位置插入一行 |
下面是<tbody>元素添加的属性和方法 | |
rows | 保存着<tbody>元素中行的HTMLCollection |
deleteRow(pos) | 删除指定位置的行 |
insertRow(pos) | 向rows 集合中的指定位置插入一行,并返回引用 |
以下是<tr>元素添加的属性和方法 | |
cells | 保存着<tr>元素中单元格的HTMLCollection |
deleteCell(pos) | 删除指定位置的单元格 |
insertCell(pos) | 向cells 集合的指定位置插入一个单元格,并返回引用 |
用这些方法和属性,我们可以写一个HTML DOM写的表格
//创建table
var table = document.createElement('table');
table.border = 1;
table.width = 300;
table.createCaption().innerHTML = '人员表';
var thead = table.createTHead();
var tr = thead.insertRow(0);
tr.insertCell(0).innerHTML = '数据1';
tr.insertCell(1).innerHTML = '数据2';
tr.insertCell(2).innerHTML = '数据3';
//将表格添加到文本主体中 document.body.appendChild(table);