JavaScript基础——文档对象模型(DOM)

DOM是语言中立的API,用于访问和操作HTML和XML文档。DOM1级将HTML和XML文档形象地看做一个层次化的节点数,

可以使用JavaScript来操作这个节点树,进而改变底层文档的外观和结构。

DOM由各种节点构成,简要总结如下:

1)最基本的节点类型是Node,用于抽象地表示文档中一个独立的部分;所有其他类型都继承自Node.

2)Document类型表示整个文档,是一组分层节点的根节点。在JavaScript中,document对象是Document的一个实例。

使用document对象,有很多种方式可以查询和取得节点。

3)Element节点表示文档中的所有HTML或XML元素,可以用来操作这些元素的内容和特性。

4)另外还有一些节点类型,分别表示文本内容、注释、文档类型、CDATA区域和文档片段。


访问DOM的操作在多数情况下都很直观,不过在处理<script>和<style>元素时还是存在一些复杂性。

由于这两个元素分别包含脚本和样式信息,因此浏览器通常会将它们与其他元素区别对待。

这些区别导致了在针对这些元素适用innerHTML时,以及在创建新元素时的一些问题。

理解DOM的关键,就是理解DOM对性能的影响。DOM操作往往是JavaScript程序中开销最大的部分,

而因当问NodeList导致的问题为最多。NodeList对象都是“动态的”,这就意味着每次访问NodeList对象,

都会运行一次查询。有鉴于此,最好的办法就是尽量减少DOM操作。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文档对象模型(DOM)</title>
</head>
<body>
<div id="div1">
    <p name="p1">段落1</p>
    <p>段落2</p>
    <p>段落3</p>
    <img src="" name="myImage"/>
    <img src="" name="myImage"/>
</div>
<div id="myDiv"><!--a comment --></div>
<ul id="myList"></ul>

<script src="l10.js"></script>
</body>
</html>


/*
 * 文档对象模型(DOM)
 */
function cl(x){
    console.log(x);
}
/**
 * 10.1 节点层次
 */

//10.1.1 Node类型 nodeType
Node.ELEMENT_NODE;//1
Node.ATTRIBUTE_NODE;//2
Node.TEXT_NODE;//3
Node.CDATA_SECTION_NODE;//4
Node.ENTITY_SECTION_NODE;//5
Node.ENTITY_NODE;//6
Node.PROCESSING_INSTRUCTION_NODE;//7
Node.COMMENT_NODE;//8
Node.DOCUMENT_NODE;//9
Node.DOCUMENT_TYPE_NODE;//10
Node.DOCUMENT_FRAGMENT_NODE;//11
Node.NOTATION_NODE;//12
//判断节点类型
var div1Element=document.getElementById("div1");
if(div1Element.nodeType==1){
    cl("div1是一个元素");
}
//10.1.1.1 nodeName和nodeValue属性
//对于元素节点,nodeName中保存的始终是元素的标签名,而nodeValue的值则始终为null
cl(div1Element.nodeName);   //=>DIV
cl(div1Element.nodeValue);  //=>null
//10.1.1.2 节点关系
//childNodes——子节点集合(NodeList)
var firstChild=div1Element.childNodes[0];
var secondChild=div1Element.childNodes.item(1);
var count=div1Element.childNodes.length;
cl(count);//=>7 所有子节点数量
//将NodeList对象转换为数组
function convertToArray(nodes){
    var array=null;
    try{
        array=Array.prototype.slice.call(nodes,0);//针对IE9及以上浏览器
    }catch(ex){//针对IE8及以下浏览器
        array=new Array();
        for(var i= 0,len=nodes.length;i<len;i++){
            array.push(nodes[i]);
        }
    }
    return array;
}
//parentNode——父节点
//previousSibling——上一个兄弟节点
//nextSibling——下一个兄弟节点
//firstChild——第一个子节点
//lastChild——最后一个子节点
//hasChildNodes()——是否包含子节点
//ownerDocument——整个文档的文档节点
cl(div1Element.ownerDocument);  //=>Document
//10.1.1.3 操作节点:操作某个节点的子节点
//appendChild(newNode)——向childNodes列表的末尾添加一个节点
var returnedNode=div1Element.appendChild(div1Element.firstChild);
cl(returnedNode==div1Element.lastChild);//=>true
//insertBefore(newNode,someNode)——插入一个兄弟节点
//replaceChild(newNode,oldNode)——替换原来的一个子节点
//removeChild(oldNode)——移除一个子节点
//10.1.1.4 操作节点的其他方法
//cloneNode()——用于创建调用这个方法的节点的一个完全相同的副本
var deepList=div1Element.cloneNode(true);
cl(deepList.childNodes.length); //=>7
var shallowList=div1Element.cloneNode(false);
cl(shallowList.childNodes.length); //=>0
//normalize()——处理文档树中的文本节点

//10.1.2 Document类型
//document对象是HTMLDocument的一个实例,表示整个HTML页面。
//Document节点具有下列特征:
//nodeType的值为9;
//nodeName的值为"#document";
//nodeValue的值为null;
//parentNode的值为null;
//ownerDocument的值为null
//其子节点可能是一个DocumentType(最多一个)、Element(最多一个)、ProcessingInstruction或Comment。
//10.1.2.1 文档的子节点
var html=document.documentElement;
cl(html.nodeName);  //=>HTML
var body=document.body;
cl(body.nodeName);  //=>BODY
var doctype=document.doctype;
cl(doctype===document.childNodes[0]);//=>true 在IE9+及Firefox
//10.1.2.2 文档信息
//取得文档标题
var originalTitle=document.title;
//设置文档标题
document.title="文档对象模型";
//取得完整的URL
cl(document.URL);
//取得域名
cl(document.domain);
//取得来源页面的URL
cl(document.referrer);//=>null
//10.1.2.3 查找元素
//getElementById()
//getElementsByTagName()
//getElementsByName()
var images=document.getElementsByTagName("img");
//var myImage=images.namedItem("myImage");
var myImage=images["myImage"];
//10.1.2.4 特殊集合
document.anchors;//所有带name特性的<a>元素
document.links;//所有带href特性的<a>元素
document.images;//所有<img>元素
document.forms;//所有<form>元素
//10.1.2.5 DOM一致性检测
var hasXMLDom=document.implementation.hasFeature("XML","1.0");
cl(hasXMLDom);//=>true
//10.1.2.6 文档写入
//write()、writeln()——写入文本到输出流
// open()和close()——打开和关闭网页的输出流

//10.1.3 Element类型
//Element节点具有以下特征:
//nodeType的值为1;
//nodeName的值为元素的标签名
//nodeValue的值为null;
//parentNode可能是Document或Element
//其子节点可能是Element、Text、Comment、processingInstruction、CDATASection或EntityReference
cl(div1Element.tagName==div1Element.nodeName);//=>true
//10.1.3.1 HTML元素
//每个HTML元素中存在的标准特性:id,title,className,lang(很少用),dir(很少用)
//10.1.3.2 取得特性 getAttribute()
//10.1.3.3 设置特性 setAttribute()、removeAttribute()
//10.1.3.4 attributes属性
//迭代元素的每一个特性,然后将它们构造成name="value"这样的字符串格式
function outputAttributes(element){
    var pairs=new Array(),
        attrName,
        attrValue,
        i,
        len;
    for(i=0,len=element.attributes.length;i<len;i++){
        attrName=element.attributes[i].nodeName;
        attrValue=element.attributes[i].nodeValue;
        if(element.attributes[i].specified){//针对IE及以下
            pairs.push(attrName+"=\""+attrValue+"\"");
        }
    }
    return pairs.join(" ");
}
//10.1.3.5 创建元素
//document.createElement()
var div=document.createElement("div");
div.id="myNewDiv";
div.className="box";
document.body.appendChild(div);
//10.1.3.6 元素的子节点

//10.1.4 Text类型
//Text节点具有以下特征:nodeType的值为3,nodeName的值为"#text",nodeValue或data的值为节点所包含的文本,parentNode是一个Element,没有子节点
//使用下列方法可以操作节点中的文本:
//appendData(text):将text添加到节点的末尾
//deleteData(offset,count):从offset指定的位置开始删除count个字符
//insertData(offset,text):在offset指定的位置插入text
//replaceData(offset,count,text):用text替换从offset指定的位置开始到offset+count为止处的文本
//splitText(offset):从offset指定的位置将当前文本节点分成两个文本节点
//substringData(offset,count):提取从offset指定的位置开始到offset+count为止处的字符串。
//10.1.4.1 创建文本节点
//document.createTextNode()
var element=document.createElement("div");
element.className="message";
var textNode=document.createTextNode("Hello world!");
element.appendChild(textNode);
var anotherTextNode=document.createTextNode("Jason,see you later.");
element.appendChild(anotherTextNode);
document.body.appendChild(element);
//10.1.4.2 规范化文本节点 normalize():合并文本节点
cl(element.childNodes.length);  //=>2
element.normalize();
cl(element.childNodes.length);  //=>1
cl(element.firstChild.nodeValue);//=>Hello world!Jason,see you later.
//10.1.4.3 分割文本节点 splitText()
var newNode=element.firstChild.splitText(12);
cl(element.firstChild.nodeValue);   //=>"Hello world!"
cl(newNode.nodeValue);  //=>"Jason,see you later."
cl(element.childNodes.length);//=>2

//10.1.5 Comment类型
//注释在DOM中是通过Comment类型来标示的。Comment节点具有下列特征:
//nodeType的值为8,nodeName的值为"#comment",nodeValue的值是注释的内容;parentNode可能是Document或Element;没有子节点
var commentDiv=document.getElementById("myDiv");
var comment=commentDiv.firstChild;
cl(comment.data);//=>a comment

//10.1.6 CDATASection类型
//CDATASection类型只针对基于XML的文档,标示的是CDATA区域。CDATASection节点具有下列特征:
//nodeType的值为4;nodeName的值为"#cdata-section";nodeValue的值是CDATA区域中的内容;parentNode可能是Document或Element;没有子节点

//10.1.7 DocumentType类型
//DocumentType包含着与文档doctype有关的所有信息,具有下列特征:
//nodeType的值为10;nodeName的值为doctype的名称;nodeValue的值为null;parentNode是Document;没有子节点

//10.1.8 DocumentFragment类型
//DOM规定文档片段(document fragment)是一种"轻量级"的文档,可以包含和控制节点,但不会像完整的文档那样占用额外的资源
//DocumentFragment节点具有下列特征:
//nodeType的值为11;
//nodeName的值为"#document-fragment";
//nodeValue的值为null;
//parentNode的值为null;
//子节点可以是Element、ProcessingInstruction、Comment、Text、CDATASection或EntityReference
var fragment=document.createDocumentFragment();
var ul=document.getElementById("myList");
var li=null;
for(var i=0;i<3;i++){
    li=document.createElement("li");
    li.appendChild(document.createTextNode("Item"+(i+1)));
    fragment.appendChild(li);
}
ul.appendChild(fragment);

//10.1.9 Attr类型
//特性节点具有下列特征:
//nodeType的值为11;nodeName的值是特性的名称;nodeValue的值是特性的值;parentNode的值为null;在HTML中没有子节点,在XML中子节点可以是Text或EntityReference
//Attr对象有3个属性:name、value和specified

/**
 * 10.2 DOM操作技术
 */

//10.2.1 动态脚本
//创建动态脚本有两种方法:插入外部文件和直接插入JavaScript代码
//<script type="text/javascript" src="client.js"></script>
function loadScript(url){
    var script=document.createElement("script");
    script.type="text/javascript";
    script.src=url;
    document.body.appendChild(script);
}
//loadScript("client.js");

//10.2.2 动态样式
//动态样式实在页面加载完成后动态添加到页面中的。
//<link rel="stylesheet" type="text/css" href="styles.css">
function loadStyles(url){
    var link=document.createElement("link");
    link.rel="stylesheet";
    link.type="text/css";
    link.href=url;
    var head=document.getElementsByTagName("head")[0];
    head.appendChild(link);
}
//loadStyles("style.css");

//10.2.3 操作表格
/**
 * 创建下列表格
 * <table border="1" width="100%">
 *   <tbody>
 *       <tr>
 *           <td>Cell 1,1</td>
 *           <td>Cell 2,1</td>
 *       </tr>
 *       <tr>
 *           <td>Cell 1,2</td>
 *           <td>Cell 2,2</td>
 *       </tr>
 *    </tbody>
 * </table>
 */
//创建table
var table=document.createElement("table");
table.border=1;
table.width="100%";
//创建tbody
var tbody=document.createElement("tbody");
table.appendChild(tbody);
//创建第一行
tbody.insertRow(0);
tbody.rows[0].insertCell(0);
tbody.rows[0].cells[0].appendChild(document.createTextNode("Cell 1,1"));
tbody.rows[0].insertCell(1);
tbody.rows[0].cells[1].appendChild(document.createTextNode("Cell 2,1"));
//创建第二行
tbody.insertRow(1);
tbody.rows[1].insertCell(0);
tbody.rows[1].cells[0].appendChild(document.createTextNode("Cell 1,2"));
tbody.rows[1].insertCell(1);
tbody.rows[1].cells[1].appendChild(document.createTextNode("Cell 2,2"));
//将表格添加到文档主体中
document.body.appendChild(table);

//10.2.4 使用NodeList
//从本质上说,所有Nodelist对象都是在访问DOM文档时实时运行的查询
var divs=document.getElementsByTagName("div"), i,len,div;
for(i=0,len=divs.length;i<len;i++){
    div=document.createElement("div");
    document.body.appendChild(div);
}
//一般来说,应该尽量减少访问NodeList的次数。因为每次访问NodeList,都会运行一次基于文档的查询。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值