\section{DOM}文档对象模型DOM(Document Object Module)是由W3C定义的提供与任何HTML或XML文档进行交互的API(编程接口),可以说是HTML之后的又一伟大创新。它使得用户可以通过javaScript访问HTML文档中的任意元素和内容,DOM提供的接口可以操作HTML文件中的节点。当浏览器加载一个网页后,这个网页就可以看作是文档树,由多个节点构成。所谓DOM,就是将HTML文档中各个元素按照从属关系建立起的模型。总的来说,我们可以利用DOM完成以下应用:\begin{itemize}\item 访问指定节点;\item 访问相关节点;\item 访问节点属性;\item 检查节点类型;\item 创建节点;\item 为节点添加事件;\item 操作节点。\end{itemize}\subsection{HTML文档与DOM}我们先看下面这个简单的HTML文档:\begin{lstlisting}<!DOCTYPE html><html lang="zh"><head><meta charset="utf-8"><title>一个简单的HTML文档</title></head><body><h1>这是一个简单的HTML文档</h1><p>文档中包含着段落和<a title="link" href="#">超级链接</a></p></body></html>\end{lstlisting}这个HTML文档的DOM可示例如下图\ref{fig:DOM}:\begin{figure}[htbp]\centering\includegraphics[width=120mm]{raw/DOM.pdf}\caption{DOM模型}\label{fig:DOM}\end{figure}在上面的DOM中,html位于最顶端,是DOM的跟节点,head和body是html的子节点,它们属于同一层,并不互相包含,是兄弟关系,h1和p是兄弟元素,其父元素是body,p的子元素是a元素。\subsection{节点}节点(node)的概念来源于计算机网络,它代表网络中的一个连接点。在DOM中,文档也是由节点构成的集合。DOM定义了多种节点,常用的是元素节点、文本节点、和属性节点,分别对应元素、元素中包含的文字内容和元素的属性。例如上面的代码中:\begin{lstlisting}<a title="link" href="#">超级链接</a>\end{lstlisting}a元素的title和href属性就是a元素节点的属性节点,a元素所包含的内容"超级链接"就是文本节点。如下图\ref{fig:node}所示:\begin{figure}[htbp]\centering\includegraphics[width=120mm]{raw/node.pdf}\caption{各种节点及关系}\label{fig:node}\end{figure}\subsection{使用DOM}DOM提供了一种访问文档内容的机制,我们可以使用DOM处理HTML文档的内容。DOM由节点(node)构成,每一个节点,都有一系列的属性、方法可以使用,常用属性、方法见下表\ref{tab:node常用属性和方法}:% Table generated by Excel2LaTeX from sheet 'Sheet1'\begin{table}[htbp]\centering\caption{node常用属性和方法}\begin{tabularx}{\linewidth}{X|X|X}\toprule{属性/方法} & {类型/返回类型} & {说明} \\\midrulenodeName & String & 节点名称 \\\hlinenodeValue & String & 节点的值 \\\hlinenodeType & Number & 节点类型 \\\hlinefirstChild & Node & childNodes列表的第一个节点 \\\hlinelastChild & Node & childNodes列表的最后一个节点 \\\hlinechildNodes & NodeList & 所有子节点列表,方法item(i)可以访问其中节点 \\\hlineparentNode & Node & 父节点 \\\hlinepreviousSibling & Node & 指向前一个兄弟节点 \\\hlinenextSibling & Node & 指向后一个兄弟节点 \\\hlinehasChildNodes() & Boolean & 是否包含子节点 \\\hlineattributes & NameNodeMap & 包含一个元素特性的Attr对象 \\\hlineappendChild(node) & Node & 将node节点添加到childNodes末尾 \\\hlineremoveChild(node) & Node & 从childNOdes中删除node节点 \\\hlinerepaceChild(new,old) & Node & 将childNodes中的oldnode节点替换为newnode节点 \\\hlineinsertBefore(new,ref) & Node & 在childNOdes中的refnode节点之前插入newnode节点 \\\hlineinnerHTML & String & 读取或者设置某个标记之间的所有内容 \\\hlineclassName & String & 读取或者设置节点的CSS类别 \\\bottomrule\end{tabularx}%\label{tab:node常用属性和方法}%\end{table}%\subsubsection{访问节点}DOM提供了一些很便捷的方法来访问文档的节点,最常用的是getElementsByTagName()和getElementById(),此外比较常用的是getElementsByName()、getElementsByClassName();\begin{lstlisting}......var oLi = document.getElementsByTagName('li');for(var i = 0 in oLi) {console.log(i + '=' + oLi[i]);}console.log(oLi);console.log(oLi.length);console.log(oLi[0].childNodes[0].nodeValue);......\end{lstlisting}将访问oLi子节点列表中的第一个节点的值。\subsubsection{检测节点类型}通过节点的nodeType属性可以检测出节点的类型,DOM定义了12种类型,大多数情况下,我们用到的是以下类型:\begin{enumerate}\item ELEMENT\_NODE 元素节点 nodeType的值为1;\item ATTRIBUTE\_NODE 属性节点 nodeType的值为2;\item TEXT\_NODE 文本节点 nodeType的值为3;\end{enumerate}\subsubsection{利用父子兄关系查找节点}在获取了某个节点之后,可以通过父子关系,利用hasChildNodes()方法和childNodes属性获取该节点所包含的所有子节点。例如:\begin{lstlisting}......var oLi = document.getElementById('myList');var DOMString = "";if(oLi.hasChildNodes()){var oChild = oLi.childNodes;for(var i=0; i<oChild.length;i++){DOMString += oChild[i].nodeName + "\n";}}console.log(DOMString);......\end{lstlisting}从运行结果我们可以看出,不光有元素节点,连它们之间的空格也被当成了子节点。通过parentNode属性,可以获取父元素节点。如:\begin{lstlisting}......var myItem = document.getElementById('active');console.log(myItem.parentNode.tagName);......\end{lstlisting}DOM还提供了处理兄弟之间关系的属性和方法,如nextSibling、previousSibling。\subsubsection{设置节点属性}找到节点后,可以通过getAttribute()、setAttribute()方法取得或者设定节点的属性。\begin{lstlisting}......var myItem = document.getElementById('active');console.log(myItem.parentNode.tagName);console.log(myItem.getAttribute("title"));myItem.setAttribute("title","主要用以和用户交互");console.log(myItem.getAttribute("title"));......\end{lstlisting}\subsubsection{创建和添加节点}创建元素节点采用creatElment(),创建文本节点采用creatTextNode(),创建文档碎片节点采用creatDocumentFragment()等等。在插入元素之前,先将元素内容添加到元素节点,再将元素节点及其包含的文本节点添加到指定节点。\begin{lstlisting}......var oP = document.createElement("p");var oText = document.createTextNode("这是一个使用DOM生成的段落");oP.appendChild(oText);document.body.appendChild(oP);......\end{lstlisting}\subsubsection{删除节点}删除节点使用removeChild()方法,通常先找到要删除的节点,然后利用parentNode属性找到父节点,然后使用父节点的removeChild方法。\begin{lstlisting}......<body onload="removeLi()"><ul id="myList"><li>HTML</li><li>CSS</li><li id="active" title="JavaScript是脚本编程语言">JavaScript</li></ul><script>function removeLi() {var oLi = document.getElementById('active');oLi.parentNode.removeChild(oLi);}</script></body>......\end{lstlisting}\subsubsection{替换节点}DOM提供replaceChild()方法来替换节点,具体过程和删除节点类似,先找到想要替换的节点,再创建新节点,然后使用父节点替换方法。\begin{lstlisting}......<body onload="replaceLi()"><ul id="myList"><li>HTML</li><li>CSS</li><li id="active">JavaScript</li></ul><script>function replaceLi() {var oOldLi = document.getElementById('active');var oNewLi = document.createElement('li');var oText = document.createTextNode('ECMAScript');oNewLi.appendChild(oText);oOldLi.parentNode.replaceChild(oNewLi,oOldLi);}</script></body>......\end{lstlisting}\subsubsection{innerHTML属性}innerHTML属性虽然不是W3C DOM的组成部分,但它得到了目前主流浏览器的支持。该属性表示某个标记之间的所有内容,包括代码本身。\begin{lstlisting}var oLi = document.getElementById('active');console.log(oLi.innerHTML);oLi.innerHTML = "<a href='http://www.baidu.com'>Baidu</a>";\end{lstlisting}\subsubsection{className属性}className属性是一个非常实用的属性,可以修改一个节点的CSS类别。\begin{lstlisting}var oLi = document.getElementById('active');console.log(oLi.className);oLi.className += ' jsdemo';console.log(oLi.className);\end{lstlisting}使用className属性如果要追加CSS样式,而不是覆盖CSS样式的话,使用"+="连接运算符,另外注意不同的样式名称使用空格分割。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。