DOM详解(二)


选择符API
  • querySelector: 接收一个CSS选择符,返回与该模式匹配的第一个元素,如果没有找到匹配的元素,则返回null
    var body = document.querySelector("body");
    var myDiv = document.querySelector("#myDiv");
    var selected = document.querySelector(".selected");
    
  • querySelectorAll:接收一个CSS选择符,返回所有匹配的元素,即一个NodeList的实例
    var ems = document.getElementById("myDiv").querySelectorAll("em");
    var strongs = document.querySelectorAll("p strong");
    for(var  i = 0, len = strongs.length; i < len; i++) {
      var strong = strongs[i];
      strong.className = "important";
    }
    
  • matchesSelector:接收一个CSS选择符,如果调用元素与该选择符匹配则返回true否则返回false
    //兼容
    function matchesSelector(element, selector) {
      if(element.matchesSelector) {
        return elemnt.matchesSelector(selector);
      } else if(elemnt.msMatchesSelector) {
        return elemnt.msMatchesSelector(selector);
      } else if (elemnt.mozMatchesSelector) {
        return elemnt.mozMatchesSelector
      } else if (elemnt.webkitMatchesSelector) {
        return elemnt.webkitMatchesSelector(selector);
      } else {
        throw new Error("Not supported.");
      }
    }
    
元素遍历
  • 对于元素之间的空格,IE9及之前版本不会返回文本节点,而其他所有浏览器都会返回文本节点。这样,就导致了在使用childNodes和firstChild等属性时的行为不一致。ElementTraversal新定义了一组属性:
    • childElementCount: 返回子元素(不包括文本节点和注释)的个数
    • firstElementChild:指向第一个子元素
    • lastElementChild:指向最后一个子元素
    • previousElementSibling:指向前一个同辈元素
    • nextElementSibling:指向后一个同辈元素
  • 跨浏览器遍历1
    var i, len, child = element.firstChild;
    while (child != elemnt.lastChild) {
      if(child.nodeType == 1) {
        processChild(child);
      }
      child = child.nextSibling;
    }
    
  • 跨浏览器遍历2
    var i, len, child = elemnt.firstElementChild;
    while (child != elemnt.lastElementChild) {
      processChild(child);
      child = child.nextElementSibling;
    }
    
HTML5
  • 类相关扩充
    • getElementByClassName():接收一个参数,包含一个或多个类名的字符串(类的顺序不重要),返回带有指定类的所有元素的NodeList
    • classList属性
      • 在操作类名时,粗腰通过className属性添加、删除和替换类名。因为className中是一个字符串,所以即使只修改字符串的一部分,也必须每次都设置整个字符串的值,比如:
        <div class="bd user disables">...</div>
        var classNames = div.className.split(/\s+/);
        var pos = -1, i, len;
        for(i = 0, len = classNames.length; i < len; i++) {
        if(className[i] == "user") {
          pos = i;
          break;
        }
        }
        classNames.splice(pos, 1);
        div.className = className.join(" ");
        
      • 新增类操作方法:add(value)contains(value)remove(value)toggle(value), 例子:
        div.classList.remove("disabled");
        div.classList.add("current");
        //如果列表中已存在给定的值,删除它;如果列表中没有给定的值,添加它;
        div.classList.toggle("user");
        //判断元素中是否包含既定的类名
        if(div.classList.contains("add") && !div.classList.contains("disabled")) {
        //pass
        }
        // 迭代类名
        for(var i = 0, len = div.classList.length; i < len; i++) {
        doSomething(div.classList[i]);
        }
        
  • 焦点管理: 元素获得焦点的方式有:页面加载、用户输入和在代码中调用focus方法
    • activeElement, hasFocus()
      var button = document.getElementById("myButton");
      button.focus();
      alert(document.activeElement === button);//true
      alert(document.hasFocus());//true;检测文档是否获得焦点,可以知道用户u是否正在与页面交互
      
  • HTMLDocument的变化
    • document的readyState有两个可能的值
      • loading: 正在加载文档
      • complete:已经加载完毕文档
    • head属性:
      var head = document.head || document.getElementByTagName("head")[0];
      
  • 字符集属性
    • document.charset
    • document.defaultChartset
  • 自定义数据属性:HTML5规定可以为元素添加非标准的属性,但要添加前缀data-,目的是为元素提供与渲染无关的信息或者语义化信息。这些属性可以任意添加、随便命名,只要以data-开头即可
    <div id="mydiv" data-appId="12345" data-myname="Nicholas"></div>
    var div = document.getElementById("mydiv");
    var appId = div.dataset.appId;
    
  • 插入标记
    • innerHTML
      • 为innerHTML设置HTML字符串后,浏览器会将这个字符串解析为相应的DOM树;
      • 一般来说插入<script>脚本元素是无效的;
      • 不支持的元素有:colcolgroupframesetheadhtmlstyletabletbodytheadtfoottr
      • 从源中删除所有脚本节点和时间处理程序属性:window.toStaticHTML(domString)
    • outHTML:返回调用它的元素及所有子节点
    • insertAdjacentHTML():两个参数,插入位置和插入的HTML文本
      • “beforebegin”:在当前元素之前插入一个紧邻的同辈元素
      • “afterbegin”:在第一个子元素之前插入一个新的子元素
      • “beforeend”:在最后一个子元素之后再插入新的子元素
      • “afterend”:在当前元素之后插入一个紧邻的同辈元素
元素大小
  • 偏移量:元素在屏幕上占用的所有可见空间。由高度、宽度决定(包括内边距、滚动条、边框大小)

    • offsetHeight:元素在垂直方向上占用的空间大小
    • offsetWidth:元素在水平方向上占用空间的大小
    • offsetLeft:元素左外边框至包含元素的左内边框之间的像素距离
    • offsetTop:元素上外边框至包含元素的上内边框之间的像素距离
    • 计算某个元素在页面上的偏移量
      function getElementLeft(element) {
      var actualLeft = element.offsetLeft;
      var current = element.offsetParent;
      while (current !== null) {
        actualLeft += current.offsetLeft;
        current = current.offsetParent;
      }
      return actualLeft;
      }
      
    • 所有这些偏移量都是只读的,而且每次访问需要重新计算。因此应该尽量避免重复访问这些属性;如果需要重复使用其中某些值,可以将它们保存在局部变量中,以提高性能。
  • 客户区:指元素内容及其内边距占据的空间大小

    • 确定浏览器视口大小:
      function getViewport() {
      if(document.compatMode == "BackCompat") {
        return {
          width: document.body.clientWidth,
          height: document.body.clientHeight
        }
      } else {
        return {
          width: document.documentElement.clientWidth,
          height: document.documentElement.clientHeight
        }
      }
      }
      
  • 滚动大小
遍历
  • NodeIterator:深度优先遍历
    // 返回遍历遇到的<li>元素
    var div = document.getElementById("div1");
    var filter = function (node) {
      return node.tagName.toLowerCase() == "li" ? NodeFilter.Filter_ACCEPT : NodeFilter.Filter_SKIP;
    }
    VAR iterator = document.createNodeIterator(div, NodeFilter.SHOW_ELEMENT, filter, false);
    var node = iterator.nextNode();
    while (node != null) {
       alert(node !== null);
       node = iterator.nextNode();
    }
    
  • TreeWalker
    var walker = document.createTreeWalker(div, NodeFilter.SHOW_ELEMENT, null, false);
    var node = walker.firstChild();
    while (node != null) {
      alert(node.tagName);
      node = walker.nextSibling();
    }
    
    • 区别:使用NodeIterator对象时,NodeFilter.Filter_SKIP与NodeFilter.Filter_REJECT作用相同,都是跳过指定的节点;使用TreeWalker对象,NodeFilter.Filter_SKIP会跳过响应的节点继续前进到子树的下一个节点,NodeFilter.Filter_REJECT则会跳过相应节点及整个子树

文章作者: Susie Chang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Susie Chang !
 上一篇
Vue学习(一)之概览 Vue学习(一)之概览
参考 Vue.js Vue中的无渲染组件 Vue是什么 Vue是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另
2018-10-15
下一篇 
DOM详解(一) DOM详解(一)
参考资料 《JavaScript高级教程》 《高性能JavaScript》 节点层次Node类型及对应数值 Node.ELEMENT_NODE(1) Node.ATTRIBUTE_NODE(2) Node.TEXT_NODE(3) Nod
2018-10-11
  目录