JavaScript高级程序设计(第三版) 第11 章 DOM 扩展 和 第12章

1### Menu

第11 章 DOM 扩展

11.1.1 querySelector()方法
11.1.2 querySelectorAll()方法
11.1.3 element.matches() element.webkitMatchesSelector()方法
11.2 元素遍历
HTML5 - 11.3.1 与类相关的扩充
HTML5 - 11.3.2 焦点管理
HTML5 - 11.3.3HTMLDocument的变化
HTML5 - 11.3.4 字符集属性
HTML5 - 11.3.5 自定义数据属性
HTML5 - 11.3.6 插入标记
    1. innerHTML 属性
    1. outerHTML 属性
    1. insertAdjacentHTML()方法
    1. 内存与性能问题
11.4 专有扩展
  • 11.4.1 文档模式
  • 11.4.2 children属性
  • 11.4.3 contains()方法 & compareDocumentPosition()方法
  • 11.4.4 插入文本
    - 1. innerText 属性
    - 2. outerText 属性
  • 11.4.5 滚动

第12 章 DOM2 和DOM3

12.2 样式
  • 12.2.1 访问元素的样式
      1. DOM 样式属性和方法
      1. 计算的样式
  • 12.2.2 操作样式表
      1. CSS 规则
      1. 创建规则
      1. 删除规则
  • 12.2.3 元素大小
      1. 偏移量
      1. 客户区大小
      1. 滚动大小
      1. 确定元素大小
  • 12.3 遍历
    • 12.3.1 NodeIterator
    • 12.3.2 TreeWalker
  • 12.4 范围
    • 12.4.1 DOM中的范围
        1. 用 DOM 范围实现简单选择
        1. 用 DOM 范围实现复杂选择
        1. 操作 DOM 范围中的内容
        1. 插入 DOM 范围中的内容
        1. 折叠 DOM 范围
        1. 比较 DOM 范围
        1. 复制 DOM 范围
        1. 清理 DOM 范围

  • 11.1.1 querySelector()方法
  • querySelector()方法接收一个 CSS 选择符,返回与该模式匹配的第一个元素,如果没有找到匹配的元素,返回 null。
//取得 body 元素
var body = document.querySelector("body");
//取得 ID 为"myDiv"的元素
var myDiv = document.querySelector("#myDiv");
//取得类为"selected"的第一个元素
var selected = document.querySelector(".selected");
//取得类为"button"的第一个图像元素
var img = document.body.querySelector("img.button");
  • 通过 Document 类型调用 querySelector()方法时,会在文档元素的范围内查找匹配的元素。而通过 Element 类型调用 querySelector()方法时,只会在该元素后代元素的范围内查找匹配的元素。
  • CSS 选择符可以简单也可以复杂,视情况而定。如果传入了不被支持的选择符, querySelector()会抛出错误。

  • 11.1.2 querySelectorAll()方法
  • querySelectorAll() 方法接收的参数与 querySelector()方法一样,都是一个 CSS 选择符,返回的是一个 NodeList 的实例。
  • 只要传给 querySelectorAll()方法的 CSS 选择符有效,该方法都会返回一个 NodeList 对象,而不管找到多少匹配的元素。如果没有找到匹配的元素, NodeList 就是空的。
  • 与 querySelector()类似,能够调用 querySelectorAll()方法的类型包括 Document、DocumentFragment 和 Element。
//取得某
中的所有元素(类似于 getElementsByTagName("em")) var ems = document.getElementById("myDiv").querySelectorAll("em"); //取得类为"selected"的所有元素 var selecteds = document.querySelectorAll(".selected"); //取得所有

元素中的所有元素 var strongs = document.querySelectorAll("p strong");

  • 要取得返回的 NodeList 中的每一个元素,可以使用 item()方法,也可以使用方括号语法
var i, len, strong;
for (i=0, len=strongs.length; i < len; i++){
strong = strongs[i]; //或者 strongs.item(i)
strong.className = "important";
}

11.1.3 element.matches() element.webkitMatchesSelector()方法
  • 这个方法接收一个参数,即 CSS 选择符,如果调用元素与该选择符匹配,返回 true;否则,返回 false。
  • 在取得某个元素引用的情况下,使用这个方法能够方便地检测它是否会被 querySelector() 或 querySelectorAll()方法返回。
  • webkitMatchesSelector() // 除了IE其它浏览器用这个方法match
  • msMatchesSelector():IE浏览器用这个方法
if (document.body.webkitMatchesSelector("body.page1")){
  //true
}

  • 11.2 元素遍历
  • 在使用 childNodes时会返回除了元素节点以外的所有节点,为了弥补这一差异,而同时又保持 DOM 规范不变, Element Traversal 规范(www.w3.org/TR/ElementTraversal/)新定义了一组属性。
  • Element Traversal API 为 DOM 元素添加了以下 5 个属性。
  • childElementCount:返回子元素(不包括文本节点和注释)的个数。
  • firstElementChild:指向第一个子元素; firstChild 的元素版。
  • lastElementChild:指向最后一个子元素; lastChild 的元素版。
  • previousElementSibling:指向前一个同辈元素; previousSibling 的元素版。
  • nextElementSibling:指向后一个同辈元素; nextSibling 的元素版。
    支持的浏览器为 DOM 元素添加了这些属性,利用这些元素不必担心空白文本节点

  • HTML5 - 11.3.1 与类相关的扩充
  • 1. getElementsByClassName()方法
  • 可以通过 document对象及所有 HTML 元素调用该方法;
  • getElementsByClassName()方法接收一个参数,该参数可以是一个或多个类名字符串,通过空格分隔;
  • 该方法会返回element或document的后代元素中匹配的元素,返回的是NodeList动态集合类型;
//取得所有类中包含"username"和"current"的元素,类名的先后顺序无所谓
var allCurrentUsernames = document.getElementsByClassName("username current");
//取得 ID 为"myDiv"的元素中带有类名"selected"的所有元素
var selected = document.getElementById("myDiv").getElementsByClassName("selected");
  • 2. classList 属性
  • 通过 className 属性为element添加、删除和替换类名。
  • 这个 classList 属性是新集合类型 DOMTokenList 的实例。与其他 DOM 集合类似;
  • DOMTokenList 有一个表示自己包含多少元素的 length 属性,而要取得每个元素可以使用 item()方法,也可以使用方括号语法。此外,这个新类型还定义如下方法。
  • add(value):将给定的字符串值添加到列表中。如果值已经存在,就不添加了。
  • contains(value):表示列表中是否存在给定的值,如果存在则返回 true,否则返回 false。
  • remove(value):从列表中删除给定的字符串。
  • toggle(value):如果列表中已经存在给定的值,删除它;如果列表中没有给定的值,添加它。
//删除"disabled"类
div.classList.remove("disabled");
//添加"current"类
div.classList.add("current");
//切换"user"类
div.classList.toggle("user");
//确定元素中是否包含既定的类名
if (div.classList.contains("bd") && !div.classList.contains("disabled")){
//执行操作
)
//迭代类名
for (var i=0, len=div.classList.length; i < len; i++){
doSomething(div.classList[i]);
}

HTML5 - 11.3.2 焦点管理
  • document.activeElement 属性,这个属性始终会引用 DOM 中当前获得了焦点的元素。
  • 元素获得焦点的方式有页面加载、用户输入(通常是通过按 Tab 键)和在代码中调用 focus()方法。
var button = document.getElementById("myButton");
button.focus();
alert(document.activeElement === button); //true
  • document.hasFocus()方法,这个方法用于确定文档是否获得了焦点。
var button = document.getElementById("myButton");
button.focus();
alert(document.hasFocus());   //true

11.3.3 HTML5 - HTMLDocument的变化
  • 1. readyState 属性
  • Document 的 readyState 属性有两个可能的值:
    • loading,正在加载文档;
    • complete,已经加载完文档。
if (document.readyState == "complete"){
//执行操作
}
  • 2. 兼容模式

  • 检测页面的兼容模式 document.compatMode ;

  • 在标准模式下, document.compatMode 的值等于"CSS1Compat",

  • 而在混杂模式下, document.compatMode 的值等于"BackCompat"

  • 3. head 属性

  • document.head 属性,引用文档的元素。


HTML5 - 11.3.4 字符集属性
  • charset
  • charset属性表示文档中实际使用的字符集,也可以用来指定新字符集。
  • 默认情况下,这个属性的值为"UTF-16",但可以通过元素、响应头
    部或直接设置 charset 属性修改这个值。来看一个例子。
alert(document.charset); //"UTF-16"
document.charset = "UTF-8";
  • defaultCharset
  • 另一个属性是 defaultCharset,表示根据默认浏览器及操作系统的设置,当前文档默认的字符集应该是什么。如果文档没有使用默认的字符集,那 charset 和 defaultCharset 属性的值可能会不一样;

HTML5 - 11.3.5 自定义数据属性
  • HTML5 规定可以为元素添加非标准的属性,但要添加前缀 data-,目的是为元素提供与渲染无关的信息,或者提供语义信息。这些属性可以任意添加、随便命名,只要以 data-开头即可。
  • 添加了自定义属性之后,可以通过元素的 dataset 属性来访问自定义属性的值。 dataset 属性的值是 DOMStringMap 的一个实例,也就是一个名值对儿的映射。
var div = document.getElementById("myDiv");
//取得自定义属性的值
var appId = div.dataset.appId;
var myName = div.dataset.myname;
//设置值
div.dataset.appId = 23456;
div.dataset.myname = "Michael";

HTML5 - 11.3.6 插入标记
  • 1. innerHTML 属性
  • 在读模式下, innerHTML 属性返回与调用元素的所有子节点(包括元素、注释和文本节点)对应的 HTML 标记。
  • 在写模式下, innerHTML 会根据指定的值创建新的 DOM 树,然后用这个 DOM 树完全替换调用元素原先的所有子节点。
  • 在子节点的内容被替换后,被替换的元素节点的属性,事件处理等还会留在属性里,所以需要先删除属性和的事件,在做替换;
div = document.createElement("div");
div.innerHTML = "outside left bold font... out right";
document.body.appendChild(div)
  • 并不是所有元素都支持 innerHTML 属性。不支持 innerHTML 的元素有: 、 、、 、 、

    in div paragraph..

    • 12.3.2 TreeWalker
      • TreeWalker 是 NodeIterator 的一个更高级的版本。除了包括 nextNode()和 previousNode()在内的相同的功能之外,这个类型还提供了下列用于在不同方向上遍历 DOM 结构的方法。
      • 方法
        • parentNode():遍历到当前节点的父节点;
        • firstChild():遍历到当前节点的第一个子节点;
        • lastChild():遍历到当前节点的最后一个子节点;
        • nextSibling():遍历到当前节点的下一个同辈节点;
        • previousSibling():遍历到当前节点的上一个同辈节点。
        //可以用 TreeWalker来代替 NodeIterator
        var div = document.getElementById("div1");
        var filter = function(node){
            return node.tagName.toLowerCase() == "li"?
                NodeFilter.FILTER_ACCEPT :
                NodeFilter.FILTER_SKIP;
        };
        var walker= document.createTreeWalker(div, NodeFilter.SHOW_ELEMENT,
            filter, false);
        var node = iterator.nextNode();
        while (node !== null) {
            alert(node.tagName); //输出标签名
            node = iterator.nextNode();
        }
    
    • filter 可以返回的值有所不同。除了 NodeFilter.FILTER_ACCEPT 和 NodeFilter.FILTER_SKIP 之外,还可以使用 NodeFilter.FILTER_REJECT, 会跳过相应节点及该节点的整个子树。例如,将前面例子中的
      NodeFilter.FILTER_SKIP 修改成 NodeFilter.FILTER_REJECT,结果就是不会访问任何节点。这是因为第一个返回的节点是
      ,它的标签名不是"li",于是就会返回 NodeFilter.FILTER_REJECT,这意味着遍历会跳过整个子树。在这个例子中,
      元素是遍历的根节点,于是结果就会停止遍历。
    • TreeWalker 真正强大的地方在于能够在 DOM 结构中沿任何方向移动。使用 TreeWalker遍历 DOM 树,即使不定义过滤器,也可以取得所有
    • 元素。
        var div = document.getElementById("div1");
        var walker = document.createTreeWalker(div, NodeFilter.SHOW_ELEMENT, null, false);
        walker.firstChild(); //转到

    walker.nextSibling(); //转到

      var node = walker.firstChild(); //转到第一个
    • while (node !== null) { alert(node.tagName); node = walker.nextSibling(); }
    • TreeWalker 类型还有一个属性:currentNode
      • 表示任何遍历方法在上一次遍历中返回的节点。通过设置这个属性也可以修改遍历继续进行的起点。
        var node = walker.nextNode();
        alert(node === walker.currentNode); //true
        walker.currentNode = document.body; //修改起点
    
    12.4 范围
    • 12.4.1 DOM中的范围
      • document.createRange()来创建 DOM 范围
      • startContainer:range起始节点的父节点(即选区中第一个节点的父节点)。
      • startOffset:范围中选中第一个节点在其父节点的 childNodes 集合中的索引。
      • endContainer:range最终节点的父节点(即选区中最后一个节点的父节点)。
      • endOffset:范围中最后一个子节点(终点)在其父节点的 childNodes 集合中的索引。如果selectNode 选择的只有一个节点,那么endOffset会返回startOffset的值+1
      • commonAncestorContainer: startContainer 和 endContainer 共同的祖先节点在文档树中位置最深的那个(也就是离startContainer 和 endContainer 最近的共同祖先节点 )。
    • 1. 用 DOM 范围实现简单选择
      • selectNode() :选择整个节点,包括其子节点;
      • selectNodeContents(): 只选择节点的子节点。
        • p contentbold fontp content

    
    
        
            

    Hello world!

    • 其他方法
      • setStartBefore(Node):将范围的起点设置在 Node 之前,因此 Node 也就是范围选区中的第一个子节点。
      • setStartAfter(Node):将范围的起点设置在 Node 之后,因此 Node 也就不在范围之内了,其下一个同辈节点才是范围选区中的第一个子节点。
      • setEndBefore(Node):将范围的终点设置在 Node 之前,因此 Node 也就不在范围之内了,其上一个同辈节点才是范围选区中的最后一个子节点。
      • setEndAfter(Node):将范围的终点设置在 Node 之后,因此 Node 也就是范围选区中的最后一个子节点。
    1. ol Coffee
    2. ol Tea
    3. ol Milk

    a paragraph line...

    • ul Coffee
    • ul Tea
    • ul Milk

    • 2. 用 DOM 范围实现复杂选择
      • setStart() 方法
        • 根据参数选择range第一个节点, 参数一传入start节点的父节点(startContainer), 参数二传入start节点在父节点中的索引(startOffset)。
      • setEnd() 方法
        • 根据参数选择range最后一个节点, 参数一传入end节点的父节点(endContainer), 参数二传入end节点在父节点中的索引加1(endOffset)。
    
    ol Coffee ol Tea ol Milk a paragraph line... ul Coffee ul Tea ul Milk
    
    1. ol Coffee
    2. ol Tea
    3. ol Milk

    a paragraph line...

    • ul Coffee
    • ul Tea
    • ul Milk

    • 3. 操作 DOM 范围中的内容

    • deleteContents()

      • Range.deleteContents() 移除来自 Document的Range 内容。
    • extractContents()

      • Range.extractContents() 也会从文档中移除范围选区。但是会返回一个[object DocumentFragment] ,就是range中的范围;
    • Range.cloneContents()

      • 返回 clone 的 Range。 返回是[object DocumentFragment] ;

    • 4.插入 DOM 范围中的内容

    • Range.insertNode(Node) 是在Range的起始位置插入节点。

    • 该方法将把指定的节点(和它的所有子孙节点)插入文档范围的开始点。当该方法返回时,当前范围将包括新插入的节点。如果 newNode 已经是文档的一部分,那么它将被从当前位置删除,然后重新插入范围的开始点。如果 newNode 是 DocumentFragment 节点,那么插入的不是它自身,而是它的子孙节点,按顺序插入范围的开始点。

    • 如果包含当前范围的开始点的节点是 Text 节点,那么在发生插入操作前,它将被分割成两个相邻的节点。如果 newNode 是 Text 节点,在插入文档后,它不会与任何相邻的 Text 节点合并。要合并相邻的节点,需要调用nodeObject.normalize()方法。

    • Range.surroundContents()方法将Range对象的内容移动到一个新的节点中, 并将这个新节点放回到range区域.如果选定的Range区域包含仅有一个节点标签的Text. 那标签将不会自动成对生成,操作将失败.

        

    Hello world!

你可能感兴趣的:(JavaScript高级程序设计(第三版) 第11 章 DOM 扩展 和 第12章)