w3ctech

DOM 学习笔记

DOM

@(Keywords)[ DOM | node | Document | Element | attributes ]

@(Author)[ GreenMelon | Chinn-San-Ken | @吾南蛮野人 | 陈灿坚 ]

@(图挂了在这里下载文档)[http://pan.baidu.com/s/1hqk6QPI]

@(Date)[二0一五/Sep/11th]

Keywords: DOM | node | Document | Element | attributes

Author: GreenMelon | Chinn-San-Ken | @吾南蛮野人 | 陈灿坚

Github:

Date: 二0一五/Sep/11th

[TOC]

图挂了在这里下载文档: http://pan.baidu.com/s/1hqk6QPI

DOM概况

API

DOM(文档对象模型)是针对 HTML 和 XML 文档的一个 API (应用程序编程接口)。DOM 描绘了一个层次化的节点树

节点分成几种不同的类型,每种类型分别表示文档中不同的信息及标记。每个节点都是一个对象,因此拥有各自的特性、属性及方法,另外也与其他节点存在某种关系。节点之间的关系构成了层次。而所有页面标记则表现为一个以特定节点为根节点的树形结构。

DEMO:

<html>
  <head>
    <title> Sample Page </title>
  </head>
  <body>
    <p> Hello World! </p>
  </body>
</html>

可以将这个简单的 HTML 文档表示为一个层次结构:

Document
  Element html
    Element head
      Element title
        Text Sample Page  //文本节点

    Element body
      Element p
        Text Hello World!

文档节点(Document)是每个文档的根节点,在这个例子中,文档节点只有一个子节点,即「html」元素,我们称之为文档元素。文档元素是文档的最外层元素,文档中的其他所有元素都包含在文档元素中。每个文档只能有一个文档元素。在 HTML 中,文档元素始终是「html」元素;而在 XML 中,没有预定义的元素,因此任何元素都能成为文档元素。

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

Node 类型

DOM 1级定义了一个 Node 接口,这个接口在 Javascript 中是作为 Node 类型实现的。DOM 中的所有节点类型都继承自 Node 类型。因此所有节点类型都共享着相同的基本属性和方法。

每个节点都有一个 nodeType 属性,用于表明节点的类型。节点类型由在 Node 类型中定义的下列 12 个数值常量来表示:

  1. Node.ELEMENT_NODE(1)
  2. Node.ATTRIBUTE_NODE(2)
  3. Node.TEXT_NODE(3)
  4. Node.CDATA_SECTION_NODE(4)
  5. Node.ENTITY_REFERENCE_NODE(5)
  6. Node.ENTITY_NODE(6)
  7. Node.PROCESSING_INSTRUCTION_NODE(7)
  8. Node.COMMENT_NODE(8)
  9. Node.DOCUMENT_NODE(9)
  10. Node.DOCUMENT_TYPE_NODE(10)
  11. Node.DOCUMENT_FRAGMENT_NODE(11)
  12. Node.NOTATION_NODE(12)

操作节点

  • 访问节点的文档节点

    /**
    * ownerDocument
    */
    var documentNode = someNode.ownerDocument;  // #document
    
  • 克隆节点

    <ul>
    <li>kobe</li>
    <li>tracy</li>
    <li>curry</li>
    </ul>
    

    ```javascript /**

    • cloneNode */ var stars = document.querySelector('ul');

// 深度克隆 var deepClone = stars.cloneNode(true); console.log(deepClone.childNodes.length); // 7(3个li元素节点+4个换行的文本节点)

// 浅克隆 var shallowClone = stars.cloneNode(false); console.log(shallowClone.childNodes.length); // 0

- 访问兄弟节点
```javascript
var prevNode = someNode.previousSibling;
var nextNode = someNode.nextSibling;
  • 判断有没有子节点

    var hasChild = someNode.hasChildNodes();         // Boolean
    var hasChild = someNode.childNodes.length > 0;
    
  • 访问子节点 ```javascript var firstNode = someNode.childNodes[0]; var secondNode = someNode.childNodes.item(1); // 从0计数

var firstNode = someNode.firstChild; var lastNode = someNode.lastChild;


- 添加子节点
```javascript
/**
 * appendChild
 */
var returnNode = someNode.appendChild(newNode);
console.log(returnNode === newNode)          // true
console.log(someNode.lastChild === newNode)  // true

/**
 * 如果传入到 appendChild() 中的节点已经是文档的一部分了
 * 那就将该节点从原来的位置移到新的位置
 */
var returnNode = someNode.appendChild(someNode.firstChild);
console.log(returnNode === someNode.firstChild);  // false
console.log(returnNode === someNode.lastChild);   // true

/**
 * insertBefore(a, b) 将a插入b前
 */ 
var returnNode = someNode.insertBefore(newNode, null);
console.log(newNode === someNode.lastChild);      // true

var returnNode = someNode.insertBefore(newNode, someNode.firstChild);
console.log(returnNode === someNode.firstChild);  // true
  • 删除子节点

    /**
    * removeChild
    */ 
    var formerFirstChild = someNode.removeChild(someNode.firstChild);
    
  • 替换子节点

    /**
    * replaceChild
    */ 
    var returnNode = someNode.replaceChild(newNode, someNode.firstChild);
    

DOM Document

概况

  • javascript 通过 Document 类型表示文档
  • 在浏览器中,document 对象是 HTMLDocument(继承自 Document 类型)的一个实例,表示整个 HTML 页面
  • document 对象是 window 对象的一个属性,因此可以将其作为全局对象来访问

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

文档子节点

文档节点有两个内置的访问其子节点的属性:

  • documentElement(该属性始终指向页面中的「html」元素节点)
  • childNodes 子节点列表

文档元素子节点

文档元素子节点:DocumentElement

<!DOCTYPE html>
<html lang="zh-cmn-Hans">
  <head>
    <meta charset="UTF-8">
    <title>Document</title>
  </head>
  <body>
  </body>
</html>

documentElement 方法:

var html = document.documentElement;
console.log(html);

Alt text

我们也可以通过 children 属性和 lastChild 属性获取文档元素:

/**
 * children
 */
var html = document.children;
console.log(html);

/**
 * lastChild
 */
var html = document.lastChild;
console.log(html);

Alt text

childNodes 方法:

var domChildren = document.childNodes;
console.log(domChildren);

Alt text

通过 childNodes 属性去获取文档元素子节点,不能确定其位置。因为该属性还获取了文档类型声明(DTD)节点。如果文档节点内还有注释节点的话,则 childNodes 属性也会获取到该注释节点。

<!-- annotation -->
<!DOCTYPE html>
<html lang="zh-cmn-Hans">
</html>

Alt text

文档类型子节点

文档类型子节点:DocumentType

文档节点的另一个子节点是 DocumentType。通常将「!DOCTYPE」看成一个和文档其他部分不同的实体,可以通过 doctype 属性来访问它的信息:

var docType = document.doctype;
console.log(docType);

Alt text

但是浏览器对 document.doctype 的支持差别很大,使得这个属性的用处很有限。

注释节点

正如上面的栗子所示,如果文档节点内存在注释节点,则该注释节点也会成为文档节点的子节点。

body 属性

document 对象的 body 属性,直接指向「body」元素。

var body = document.body;

文档信息

var referrer = document.referrer,  // 来源页面的url
      domain = document.domain,    // 域名
       title = document.title,     // 标题
         url = document.url;       // 完整的url

查找元素

var      id = document.getElementById(''),          // id全局属性
      class = document.getElementsByClassName(''),  // 类名
      name  = document.getElementsByName(''),       // name全局属性
    tagName = document.getElementsByTagName('');    // 标签名

demo:

<img name="caigua" src="" alt="">
var images = document.getElementsByTagName('img'),
       img = images[0],
       img = images.item(0),
       img = images.namedItem('caigua'),
       img = images['caigua'];

Alt text

特殊集合

除了属性和方法,document 对象还有一些特殊的集合,这些集合都是 HTMLCollection 对象,为访问文档常用的部分提供了快捷方式:

document.images;   // 所有的<img>元素
document.forms;    // 所有的<form>元素
document.links;    // 所有带href属性的<a>元素
document.anchors;  // 所有带name属性的<a>元素

DOM Element

概况

Element 类型用于表现 HTML 或 XML 元素,提供了对元素标签名、子节点及属性的访问。

要访问元素的标签名,可以用 nodeName 属性,也可以用tagName 属性,这两个属性会返回相同的值。

  • 在 HTML 中,标签名始终都以全部大写表示
  • 在 XML(包括 XHTML)中,标签名始终和源代码中保持一致

Alt text

假如你不确定自己的脚本将会在 HTML 还是 XML 文档中执行,最好还是将标签名转换成相同的大小写形式:

Alt text

元素

所有的 HTML 元素都由 HTMLElement 类型表示。 HTMLElement 类型直接继承自 Element 并添加了一些属性。每个 HTML 元素中都存在下列标准属性

  • className:与元素的 class 属性对应
  • dir:元素内容的文本方向,值为 ltr 或者 rtl,很少使用
  • id:元素在文档中的唯一标识符
  • lang:元素内容的语言代码,很少使用
  • title:有关元素的附加说明信息,一般通过工具提示条显示出来

元素属性的获取

WARNING: HTML 元素的属性与 DOM 对象的属性是不同的概念

绝大多数的元素都会定义一个或多个属性,这些属性的用途是给出相应元素或其内容的附加信息。操作属性的 DOM 方法主要有三个:

/**
 * 这三种方法实际上都是操作
 * DOM节点的attributes属性中的attribute
 */
node.setAttribute('name', 'value');  // 元素属性的值为字符串!
node.getAttribute('name'); 
node.removeAttribute('name');

demo:

<body>
  <div class="melon" id="green" lang="zh-cmn-Hans"></div>
</body>

Alt text

在实际开发中,我们并不常用 getAttribute() 方法,而更多地使用对象的 property。为什么呢?比如,我们在元素上使用了 onclick 属性,绑定了点击事件处理程序,该属性包含的是 Javascript 代码。如果通过 getAttribute() 方法访问,将会返回相应代码的字符串;而通过 onclick 属性访问,则会返回 Javascript 函数。再比如,通过 getAttribute() 方法访问 style 属性,返回的是一段文本;而通过 style 属性访问,则会返回一个对象。

demo:

<body>
  <div style="height: 100px;background-color: crimson;" onclick="console.log(this.innerText)">Where Amazing Happens!</div>
</body>

Alt text

元素的attributes属性

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

NamedNodeMap 对象拥有下列方法:

setNamedItem(node);     // 添加节点,以节点的nodeName属性为索引
getNamedItem(name);     // 返回nodeName属性等于name的节点
item(pos);              // 返回位于数字pos位置的节点
removeNamedItem(name);  // 移除nodeName属性等于name的节点

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

demo:

<div class="green" id="melon"></div>
var  div = document.querySelector('div'),      // DOM对象
      id = div.attributes.id,                  // 节点对象(元素属性)
      id = div.attributes['id'],               // 节点对象(元素属性)
      id = div.attributes.getNamedItem('id'),  // 节点对象(元素属性)
      id = div.attributes.item(1),             // 节点对象(元素属性)
 id_name = div.attributes.id.name,             // 元素属性的名称
 id_name = div.attributes.id.nodeName,         // 元素属性的名称
id_value = div.attributes.id.value,            // 元素属性的值
id_value = div.attributes.id.nodeValue,        // 元素属性的值
id_value = div.getAttribute('id');             // 元素属性的值

Alt text

TIPS: 如果想要遍历元素的属性,不妨试试 attributes 属性

for (var i = 0, l = node.attributes.length; i < l; i++) {
  var nodeName = node.attributes[i].nodeName,
     nodeValue = node.attributes[i].nodeValue;
}

REFERENCE

w3ctech微信

扫码关注w3ctech微信公众号

共收到1条回复