JS之DOM

2018-08-25  本文已影响12人  LemonnYan

一、节点层次

DOM是针对 HTMLXML 文档的一个API(应用程序编程接口)。DOM描绘了一个层次化的节点树,允许开发人员添加、移除和修改页面的某一部分。

DOM文档对象模型

DOM 可以将任何 HTMLXML 文档描绘成一个由多层节点构成的结构。节点分为几种不同的类型,每种类型分别表示文档中不同的信息及(或)标记。每个节点都拥有各自的特点、数据和方法,另外也与其他节点存在某种关系。节点之间的关系构成了层次,而所有页面标记则表现为一个以特定节点为根节点的树形结构。

文档元素是文档的最外层元素,文档中的其他所有元素都包含在文档元素中。每个文档只能有一个文档元素。在 HTML 页面中,文档元素始终都是 <html> 元素。在 XML 中,没有预定义的元素,因此任何元素都可能成为文档元素。

每一段标记都可以通过树中的一个节点来表示:HTML 元素通过元素节点表示,特性(attribute)通过特性节点表示,文档类型通过文档类型节点表示,而注释则通过注释节点表示。总共有 12 种节点类型,这些类型都继承自一个基类型。

1、Node类型

DOM1 级定义了一个 Node 接口,该接口将由 DOM 中的所有节点类型实现。这个 Node 接口在JavaScript 中是作为 Node 类型实现的;除了 IE 之外,在其他所有浏览器中都可以访问到这个类型。JavaScript 中的所有节点类型都继承自 Node 类型,因此所有节点类型都共享着相同的基本属性和方法。每个节点都有一个 nodeType 属性,用于表明节点的类型。

(1) nodeName 和 nodeValue 属性

要了解节点的具体信息,可以使用 nodeName 和 nodeValue 这两个属性。这两个属性的值完全取决于节点的类型。

(2)节点关系

文档中所有的节点之间都存在相互关系。

每个节点都有一个 childNodes 属性,其中保存着一个 NodeList 对象。 NodeList 是一种类数组对象,用于保存一组有序的节点,可以通过位置来访问这些节点。请注意,虽然可以通过方括号语法来访问 NodeList 的值,而且这个对象也有 length 属性,但它并不是 Array 的实例。 NodeList 对象的独特之处在于,它实际上是基于 DOM 结构动态执行查询的结果,因此 DOM 结构的变化能够自动反映在 NodeList 对象中。

var firstChild = someNode.childNodes[0];
var secondChild = someNode.childNodes.item(1);
var count = someNode.childNodes.length;

每个节点都有一个 parentNode 属性,该属性指向文档树中的父节点。包含在 childNodes 列表中的所有节点都具有相同的父节点,因此它们的 parentNode 属性都指向同一个节点。
包含在childNodes 列表中的每个节点相互之间都是同胞节点。通过使用列表中每个节点的 previousSibling和 nextSibling 属性,可以访问同一列表中的其他节点。列表中第一个节点的 previousSibling 属性值为 null ,而列表中最后一个节点的 nextSibling 属性的值同样也为 null。

if (someNode.nextSibling === null){
    alert("Last node in the parent’s childNodes list.");
} else if (someNode.previousSibling === null){
    alert("First node in the parent’s childNodes list.");
}

所有节点都有的最后一个属性是 ownerDocument ,该属性指向表示整个文档的文档节点。这种关系表示的是任何节点都属于它所在的文档,任何节点都不能同时存在于两个或更多个文档中。通过这个属性,我们可以不必在节点层次中通过层层回溯到达顶端,而是可以直接访问文档节点。

(3)操作节点

因为关系指针都是只读的,所以 DOM 提供了一些操作节点的方法。其中,最常用的方法是appendChild() ,用于向 childNodes 列表的末尾添加一个节点。

使用insertBefore() 方法可以把节点放在 childNodes 列表中某个特定的位置上,接受两个参数:要插入的节点和作为参照的节点。

2、Document类型

在浏览器中, document 对象是 HTMLDocument (继承自 Document 类型)的一个实例,表示整个 HTML 页面。
Document 类型可以表示 HTML 页面或者其他基于 XML 的文档。不过,最常见的应用还是作为HTMLDocument 实例的 document 对象。通过这个文档对象,不仅可以取得与页面有关的信息,而且还能操作页面的外观及其底层结构。

(1)文档的子节点

documentElement属性,该属性始终指向 HTML 页面中的 <html> 元素。作为 HTMLDocument 的实例, document 对象还有一个 body 属性,直接指向 <body> 元素。

var body = document.body; //取得对<body>的引用

所有浏览器都支持 document.documentElement 和 document.body 属性。

(2)文档信息

<title> 元素中的文本——显示在浏览器窗口的标题栏或标签页上。修改 title 属性的值不会改变 <title>元素。

//取得文档标题
var originalTitle = document.title;
//设置文档标题
document.title = "New page title";

对网页的请求有关的属性:URL 、 domain 和 referrer 。

  • URL 属性中包含页面完整的 URL(即地址栏中显示的 URL);
  • domain 属性中只包含页面的域名;
  • referrer属性中保存着链接到当前页面的URL;
//取得完整的 URL
var url = document.URL;
//取得域名
var domain = document.domain;
//取得来源页面的 URL
var referrer = document.referrer;

(3)查找元素

Document 类型为此提供了两个方法: getElementById() 和 getElementsByTagName() 。
getElementById() ,接收一个参数:要取得的元素的 ID。如果找到相应的元素则返回该元素,如果不存在带有相应 ID 的元素,则返回 null 。如果页面中多个元素的 ID 值相同, getElementById() 只返回文档中第一次出现的元素。

<div id="myDiv">Some text</div>
var div = document.getElementById("myDiv"); //取得<div>元素的引用

getElementsByTagName(), 接收一个参数:要取得元素的标签名。返回的是包含零或多个元素的 NodeList 。

var   images = document.getElementsByTagName("img");
alert(images.length); //输出图像的数量
alert(images[0].src); //输出第一个图像元素的 src 特性
alert(images.item(0).src); //输出第一个图像元素的 src 特性

可以使用方括号语法或 item() 方法来访问 HTMLCollection 对象中的项。

HTMLCollection 对象还有一个方法,叫做 namedItem() ,使用这个方法可以通过元素的 name特性取得集合中的项。

<img src="myimage.gif" name="myImage">
var myImage = images.namedItem("myImage");
var myImage = images["myImage"];    //对命名的项也可以使用方括号语法来访问

getElementsByName() ,返回带有给定 name 特性的所有元素。最常使用 getElementsByName() 方法的情况是取得单选按钮;为了确保发送给浏览器的值正确无误,所有单选按钮必须具有相同的 name 特性。

 <fieldset>
        <legend>Which color do you prefer?</legend>
        <ul>
            <li>
                <input type="radio" value="red" name="color" id="colorRed">
                <label for="colorRed">Red</label>
            </li>
            <li>
                <input type="radio" value="green" name="color" id="colorGreen">
                <label for="colorGreen">Green</label>
            </li>
            <li>
                <input type="radio" value="blue" name="color" id="colorBlue">
                <label for="colorBlue">Blue</label>
            </li>
        </ul>
</fieldset>

var radios = document.getElementsByName("color");

3、Element类型

Element 类型用于表现 XML或 HTML元素,提供了对元素标签名、子节点及特性的访问。
要访问元素的标签名,可以使用 nodeName 属性,也可以使用 tagName 属性;这两个属性会返回相同的值(使用后者主要是为了清晰起见)。

<div id="myDiv"></div>
var div = document.getElementById("myDiv");
alert(div.tagName); //"DIV"
alert(div.tagName == div.nodeName); //true

在 HTML 中,标签名始终都以全部大写表示;

(1) HTML 元素

所有 HTML 元素都由 HTMLElement 类型表示或它的子类型来表示。 HTMLElement 类型直接继承自 Element 并添加了一些属性。

<div id="myDiv" class="bd" title="Body text" lang="en" dir="ltr"></div>

var div = document.getElementById("myDiv");
//获取每个属性的值
alert(div.id); //"myDiv""
alert(div.className); //"bd"
alert(div.title); //"Body text"
alert(div.lang); //"en"
alert(div.dir); //"ltr"

//为每个属性赋予新的值
div.id = "someOtherId";
div.className = "ft";
div.title = "Some other text";
div.lang = "fr";
div.dir ="rtl";

(2)取得特性

每个元素都有一或多个特性,这些特性的用途是给出相应元素或其内容的附加信息。操作特性的DOM 方法主要有三个,分别是 getAttribute() 、 setAttribute() 和 removeAttribute() 。这三个方法可以针对任何特性使用,包括那些以 HTMLElement 类型属性的形式定义的特性。

var div = document.getElementById("myDiv");
alert(div.getAttribute("id")); //"myDiv"
alert(div.getAttribute("class")); //"bd"
alert(div.getAttribute("title")); //"Body text"
alert(div.getAttribute("lang")); //"en"
alert(div.getAttribute("dir")); //"ltr"

如果给定名称的特性不存在, getAttribute() 返回 null 。

通过 getAttribute() 方法也可以取得自定义特性。

<div id="myDiv" my_special_attribute="hello!"></div>
//包含一个名为 my_special_attribute 的自定义特性,它的值是 "hello!"
var value = div.getAttribute("my_special_attribute");

特性的名称是不区分大小写的,即 "ID" 和 "id" 代表的都是同一个特性。
根据 HTML5 规范,自定义特性应该加上 data- 前缀以便验证。

(3)设置特性

setAttribute() 会以指定的值替换现有的值;如果特性不存在,setAttribute()则创建该属性并设置相应的值。

div.setAttribute("id", "someOtherId");
div.setAttribute("class", "ft");
div.setAttribute("title", "Some other text");
div.setAttribute("lang","fr");
div.setAttribute("dir", "rtl");

通过 setAttribute() 方法既可以操作 HTML 特性也可以操作自定义特性。通过这个方法设置的特性名会被统一转换为小写形式,即 "ID" 最终会变成 "id" 。

因为所有特性都是属性,所以直接给属性赋值可以设置特性的值。为 DOM 元素添加一个自定义的属性,该属性不会自动成为元素的特性。

div.id = "someOtherId";
div.align = "left";

div.mycolor = "red";
alert(div.getAttribute("mycolor")); //null(IE 除外)

removeAttribute()用于彻底删除元素的特性。调用这个方法不仅会清除特性的值,而且也会从元素中完全删除特性。

div.removeAttribute("class");

(4) attributes 属性

Element 类型是使用 attributes 属性的唯一一个 DOM节点类型。 attributes 属性中包含一个NamedNodeMap ,与 NodeList 类似,也是一个“动态”的集合。元素的每一个特性都由一个 Attr 节点表示,每个节点都保存在 NamedNodeMap 对象中。 NamedNodeMap 对象拥有下列方法。

  • getNamedItem(name) :返回 nodeName 属性等于 name 的节点;
  • removeNamedItem(name) :从列表中移除 nodeName 属性等于 name 的节点;
  • setNamedItem(node) :向列表中添加节点,以节点的 nodeName 属性为索引;
  • item(pos) :返回位于数字 pos 位置处的节点。

attributes 属性中包含一系列节点,每个节点的 nodeName 就是特性的名称,而节点的 nodeValue就是特性的值。

var id = element.attributes.getNamedItem("id").nodeValue;
//使用方括号语法通过特性名称访问节点的简写方式
var id = element.attributes["id"].nodeValue;

也可以使用这种语法来设置特性的值,即先取得特性节点,然后再将其 nodeValue 设置为新值。

//设置特性的值
element.attributes["id"].nodeValue = "someOtherId";
//删除具有给定名称的特性
var oldAttr = element.attributes.removeNamedItem("id");
//为元素添加一个新特性
element.attributes.setNamedItem(newAttr);

(5)创建元素

使用 document.createElement() 方法可以创建新元素。

var div = document.createElement("div");
//操作元素的特性,为它添加更多子节点
div.id = "myNewDiv";
div.className = "box";
//把新元素添加到文档树
document.body.appendChild(div);

//以另一种方式使用 createElement()
var div = document.createElement("<div id=\"myNewDiv\" class=\"box\"></div >");

在新元素上设置这些特性只是给它们赋予了相应的信息。由于新元素尚未被添加到文档树中,因此设置这些特性不会影响浏览器的显示。要把新元素添加到文档树,可以使用 appendChild() 、 insertBefore() 或replaceChild() 方法。

(6)元素的子节点

元素可以有任意数目的子节点和后代节点,因为元素可以是其他元素的子节点。元素的childNodes 属性中包含了它的所有子节点,这些子节点有可能是元素、文本节点、注释或处理指令。

4、Text类型

文本节点由 Text 类型表示,包含的是可以照字面解释的纯文本内容。纯文本中可以包含转义后的HTML 字符,但不能包含 HTML 代码。

(1)创建文本节点

可以使用 document.createTextNode() 创建新文本节点,这个方法接受一个参数——要插入节点中的文本。

var element = document.createElement("div");
element.className = "message";
var textNode = document.createTextNode("Hello world!");
element.appendChild(textNode);
document.body.appendChild(element);

(2)规范化文本节点

normalize()将相邻文本节点合并的方法。这个方法是由 Node 类型定义的(因而在所有节点类型中都存在)。

var element = document.createElement("div");
element.className = "message";
var textNode = document.createTextNode("Hello world!");
element.appendChild(textNode);

var anotherTextNode = document.createTextNode("Yippee!");
element.appendChild(anotherTextNode);

document.body.appendChild(element);

alert(element.childNodes.length); //2

element.normalize();
alert(element.childNodes.length); //1
alert(element.firstChild.nodeValue); // "Hello world!Yippee!"

(3)分割文本节点

splitText() 将一个文本节点分成两个文本节点。
原来的文本节点将包含从开始到指定位置之前的内容,新文本节点将包含剩下的文本。这个方法会返回一个新文本节点,该节点与原节点的parentNode 相同。

var element = document.createElement("div");
element.className = "message";

var textNode = document.createTextNode("Hello world!");
element.appendChild(textNode);
document.body.appendChild(element);

var newNode = element.firstChild.splitText(5);
alert(element.firstChild.nodeValue); //"Hello"
alert(newNode.nodeValue); //" world!"
alert(element.childNodes.length); //2

分割文本节点是从文本节点中提取数据的一种常用 DOM解析技术。

5、Comment类型

注释在 DOM 中是通过 Comment 类型来表示的。
Comment 类型与 Text 类型继承自相同的基类,因此它拥有除 splitText() 之外的所有字符串操作方法。

6、CDATASection类型

CDATASection 类型只针对基于 XML 的文档,表示的是 CDATA 区域。与 Comment 类似,CDATASection 类型继承自 Text 类型,因此拥有除splitText() 之外的所有字符串操作方法。

二、DOM操作技术

1、动态脚本

创建动态脚本也有两种方式:插入外部文件和直接插入 JavaScript 代码。

//动态加载的外部 JavaScript 文件
<script type="text/javascript" src="client.js"></script>
//创建节点的 DOM 代码
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "client.js";
document.body.appendChild(script);
//使用函数来封装
function loadScript(url){
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = url;
    document.body.appendChild(script);
}

//调用
loadScript("client.js");

2、动态样式

能够把 CSS 样式包含到 HTML 页面中的元素有两个。其中, <link> 元素用于包含来自外部的文件,而 <style> 元素用于指定嵌入的样式。
所谓动态样式是指在页面刚加载时不存在的样式;动态样式是在页面加载完成后动态添加到页面中的。

//引用
<link rel="stylesheet" type="text/css" href="styles.css">
//动态创建
var link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
link.href = "style.css";
var head = document.getElementsByTagName("head")[0];
head.appendChild(link);

//函数的形式
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("styles.css");

必须将 <link> 元素添加到 <head>而不是 <body> 元素,才能保证在所有浏览器中的行为一致。

3、操作表格

<table> 元素是 HTML 中最复杂的结构之一。要想创建表格,一般都必须涉及表示表格行、单元格、表头等方面的标签。

上一篇 下一篇

猜你喜欢

热点阅读