《JavaScript高级程序设计》Chapter 10 DOM

  • 以前提到过 DHTML->DOM
  • 本章介绍与浏览器相关的DOM节点以及JS对DOM的实现
  • 注意到,IE中的DOM都是经过COM实现的,与通常的DOM的运行机制有差别(考虑能力检测、浏览器兼容)
  • 节点层次
    • 映射 
    • Node类型(一些通用的节点方法或者属性) go
    • Document类型(注意<head>中一些网页信息的处理) go
    • Element类型(访问和处理元素属性的几种方法) go
    • Text类型(文本) go
    • Comment类型(注释) go
    • CDATASection类型(针对XML) go
    • DocumentType类型(doctype) go
    • DocumentFragment类型(子节点树的“仓库”) go
    • Attr类型(属性节点) go
  • DOM操做技术:动态脚本、动态样式、表格<table>的操做、NodeList相关注意事项。go
 

节点层次

  • DOM将HTML或者XML文件映射成节点树。从前了解的节点类型大体上分为3种(元素节点、属性节点和文档节点),然而本书中进一步细分为12种类型,继承自一个基类型。
  • 每一个节点其实是一个节点对象,能够经过获取获得,并调用相关属性和方法进行处理。
  • DOM其实是一套API,提供了各类接口(节点类型接口)。
  • Node类型(一些通用的方法和属性)
    • 存储了一些节点的通用方法,其余类型的节点都继承了这个节点。可是须要注意IE8及以前的版本并不具有这个对象类型。
    • nodeType属性。存储了一些常量,表示节点类型。
    • nodeName和nodeValue属性:顾名思义。并非全部节点的这两个属性有值,有时是null
    • 节点关系:构成了节点树,访问其余节点的方法或者属性:
      • childNodes属性:动态的NodeList,是类数组对象,具备length。能够经过Array.prototype.slice()转换为数组。注意IE8及以前的处理须要用遍历的方法处理。
      • parentNode属性
      • previousSibling属性、nextSibling属性
      • firstChild和lastChild属性
      • hasChildNodes()方法
      • ownerDocument :指向DOM节点
      • 有些节点并不存在子节点,这里会存在差别。
    • 操做节点:上述关系节点是只读的,能够经过操做节点进行一些操做。
      • appendChild():注意到若是传入的节点已是文档的一部分了,那么这个节点会转移到新的位置(指针的改变)。
      • DOM中的节点不会同时出如今两个或者多个DOM中
      • insertBefore(newNode, null/oldNode)
      • replaceChild(newNode, waitToReplacedNode)
      • 被代替的节点仍然存在在文档中,只不过在文档中没了它的位置:各类指针关系已经不存在(或者被替代了)。没法经过其余节点访问到它,因此说它没有本身的位置
      • removeChild():只是移除
      • 这些操做是在“关系”的基础上:主要由于DOM经过“关系”(指针)来访问节点
    • 其余方法:
      • cloneNode():只复制特性,不复制其余操做(如事件处理)。IE这里存在bug,建议复制以前,移除事件处理程序。
      • cloneNode(true):克隆节点以及其下完整的其余节点
      • cloneNode(false):只复制该节点,须要借助appendChild()等将其加入到文档中。
      • normalize():处理异常的文档节点(删除空白文档节点、合并相邻的文档节点)
  • Document类型
    • document与html的关系:document是HTMLDocument(继承自Document类型)的一个实例。也是window对象的属性。
    • Document节点特征:
      • nodeType为9
      • nodeName为"#document"
      • nodeValue为null
      • parentNode为null
      • ownerDocument为null
      • 其子节点多是DocumentType(最多一个)、Element(最多一个)、ProcessingInstruction或者Comment
    • 子节点
      • 多是DocumentType(最多一个)、Element(最多一个)、ProcessingInstruction或者Comment
      • document.documentElement:指向html
      • document.body:指向body
      • DocumentType:document.doctype处理<!DOCTYPE>。各浏览器处理方式不一样
      • 注释:各浏览器处理方式也不一样
      • 因为这些差别性存在,因此通常没什么用处。也不须要调用appendChild()等方法进行处理
    • 文档信息(做为HTMLDocument实例)
      • 网页的信息(放在<head>中)
      • document.title:动态改变标题栏标题(文档中的title属性不变)
      • document.url/document.domain/document.referrer:
        • 不建议改变,没多大用处:可是将多个框架的document.domain改一致,有助于通讯
        • domain不能够改的彻底不一样
        • 不可将松散的(wrox.com)改做紧绷的(p2p.wrox.com)
    • 查找元素
      • getElementById():区分大小写,返回第一个找到的id(有时会返回同名的name,因此建议name和id属性不要同样)
      • getElementsByTagName():返回相似NodeList的HTMLCollection对象。
        • getElementsByTagName(*):顺序返回全部元素
        • getElementsByTagName("*"):返回注释元素
      • HTMLCollection对象:
        • 方括号传入数字==调用item()方法
        • 方括号传入字符==调用nameItem()方法经过name属性获取
      • getElementsByName():HTMLDocument类型的方法
      • TIPS:
        • 一、对于表单元素,id不一样以使<label>元素应用到单个标签
        • 二、name相同以确保三个值只有一个给浏览器
    • 特殊集合(HTMLDocument对象):document.anchors/document.applets(已不用)/document.forms/document.images/document.links
    • DOM一致性检测:hasFeature()+必要的能力检测
    • 文档写入:write()/writeln()/open()/close()
      • 注意写入"<script>...</script>"的时候分开来,并写做"<script>..."+"<\/script>"
      • 在文档调用完毕以后执行write()/writeln()方法会重写整个页面
  • Element类型(元素节点),主要用于表现XML或者HTML文档
    • 特征:nodeType为1,nodeName为标签名,nodeValue为null,parentNode/子节点灵活。
    • nodeName属性、tagName属性访问元素的标签名,后者一概返回大写,注意这点,尤为在HTML文档中,可所有处理成小写。
    • HTML元素(由HTMLElement或者其子类型表示)
      • id/title/lang/dir/className属性。注意到没有用class是由于“class”是JS的保留字
      • 格式 div.id
    • 取得特性:getAttribute()/setAttribute()/removeAttribute()
      • getAttribute()能够取得自定义特性(不区分大小写,且HTML5中自定义特性须要加上data-前缀),而这些自定义属性是不会调价到DOM元素的属性中的(IE除外)。
    • 设置特性:setAttribute()、removeAttribute()
      • 会处理自定义属性,特姓名统一转换为小写
    • attributes属性(处理属性节点)
      • Element类型是使用这个属性的惟一一个DOM节点类型
      • 包含相似NodeList的NamedNodeMap集合。
      • element.attributes.getNamedItem("id").nodeValue
        element.attributes["id"].nodeValue
        element.attributes.removeNamedItem("id")//返回删除的属性节点
        element.attributes.setNamedItem("newAttr");
      • 不常使用。能够用在遍历元素特性上。
      • 返回的特性的顺序不必定。
    • 建立元素
      • document.creatElement("div")
      • IE中 :document.creatElement("html代码")//避开IE的一些漏洞
    • 元素子节点:对于某个标签下有多少个子节点的问题
      • IE只考虑元素类型
      • 其余浏览器还会考虑换行符(文本类型)
      • 因此注意考虑nodeType
      • 固然可使用getElementById()或者getElementsByTagName()
    • 访问or设置元素的属性方法
      • HTMLElement或者子类型方法
      • getAttribute()/setAttribute()/removeAttribute()
      • DOM对象的属性来访问:不会设置自定义属性
      • attributes属性
      • 注意:style和onclick等在getAttribute()和DOM属性调用中返回的不同:style经过getAttribute()返回CSS文本,属性返回对象;onclick等经过属性返回JS函数,getAttribute返回代码的字符串。
      • 若以编程方式操做的时候,避免使用getAttribute();getAttribute()适合处理自定义属性。
  • Text类型
    • 经过nodeValue属性、data属性以及createTextNode()等方式均可以访问或者修改Text节点(可是注意,修改时传入的字符串会通过HTML或XML的编码)
    • createTextNode()建立文本节点
    • 在element上调用element.normalize()规范下面的文本节点
    • splitText(index)分割文本节点,分割到index前一个位置为止。
    • 注意到:能够经过lastChild访问元素的文本节点(文本节点一般是元素的最后一个节点?)
  • Comment类型(注释)
    • 不支持子节点,但能够经过父节点访问(comment.data)。
    • 与Text类型继承自相同基类,拥有除了splitText()外的方法
    • document.createComment()
    • 少用。须要确保在<html></html>间,否则会有不一样的处理方式(参照Document节点类型那里的讨论)
  • CDATASection类型(针对基于XML的文档,表示CDATA区域)
    • 一样继承自Text类型,拥有除了splitText()外的方法
    • document.createCDataSection()
  • DocumentType类型
    • 仅FireFox、Safari、Opera和Chrome4.0支持
    • DOM1中不能动态建立,只能经过document.doctype访问
    • 属性:name、entities、notations;针对HTML和XHTML,后二者都是空列表。因此name属性比较有用,保存文档类型的名称。
    • 以前也提到过,不一样浏览器的处理方式不一样。
  • DocumentFragment类型
    • 轻量级。只有它在文档中没有对应的标记。包含和控制节点,但不占用额外资源。
    • 能够作“仓库”使用,保存未来可能会添加到文档中的节点(待经过appendChild()等方法添加至树中,或者从树中移除的)
    • 建立:document.createDocumentFragment();
    • 文档片断,继承了Node的全部方法。
    • 例如,为ul添加3个li:
      var fragment = document.createDocumentFragment();
      var ul = document.getElementById("ul");
      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); //fragment中的全部li被删除并转移到ul中
  • Attr类型(属性类型)
    • 通常不认为是节点树中的成员,常使用其它方法访问,而不是使用属性节点进行操做。
    • 属性:name/value/specified
    • document.createAttribute()
    • element.setAttributeNode(attr);//其中attr是属性节点
      element.getAttributeNode(attr)

DOM操做技术

    • 动态脚本
      • 经过DOM动态添加JS脚本<script>
      • 添加外部脚本:什么时候加载完毕没法确认,但能够经过“事件”进行控制。
      • 添加内嵌脚本:广泛支持向script标记添加文本节点,但IE不容许访问script的子节点,则可经过对script.text进行处理来添加这个内嵌脚本。
    • 动态样式
      • 经过DOM动态应用CSS样式:
      1. link添加样式表;
      2. style添加嵌入样式;
      3. 修改元素的属性:
        • 修改元素的样式属性;
        • 修改元素的class属性以匹配已存在的样式
      • 外部样式表是异步加载的,是否知道样式表已经加载完成并不重要。但一样能够经过“事件”对这个过程进行检测。
      • 对于<style>标记,IE一样不能够访问其子节点,这个时候能够经过style.stylesheet.cssText处理。注意处理这个属性有可能致使浏览器崩溃。
    • 操做表格<table>元素
      • <table>,<tbody>/<thead>,<tr>,<th>/<td>对于多行多列的表格须要进行大量的重复性工做,HTML DOM为此给<table>,<tbody>,<tr>增长了一些属性和方法。
      • 还能够利用document.write() or innerHTML写入建立的代码,其中行列能够经过双重for循环处理,注意须要采起尽可能少的调用innerHTML的循环算法,考虑内存的使用状况。
    • 使用NodeList(如getElementsByTagName)的注意事项
      • 以及NamedNodeMap和HTMLCollection都是类数组对象,且都是动态的:文档结构变化的时候,他们随之改变(实时运行的查询)
      • 每次从新访问NodeList等的时候,都会从新对NodeList进行查询,更新其length属性,因此效率略低,应该减小对NodeList等的访问,而且能够将其中取得的值缓存起来使用(而不是每次都去查询一遍)
      • 理解DOM的关键,就是理解DOM对性能的影响。DOM操做每每是JS程序最大的开销部分
相关文章
相关标签/搜索