《DOM探索之基础详解篇》笔记

慕课网 DOM探索之基础详解篇 学习笔记

一、认识DOM

  • DOM 提供了用程序来动态控制HTML的接口。
  • DOM级别:
    • DOM 0级:实际上是不存在的,只是DOM历史坐标系的一个参照点而已,多指DHTML。
    • DOM 1级:DOM core,DOM HTML.
    • DOM 2级:DOM Views,DOM Events,DOM Style,DOM Traversal and Range.
    • DOM 3级:DOM Load And Save,DOM Validation.
  • Web浏览器对DOM的支持:
《DOM探索之基础详解篇》笔记_第1张图片
3c49055b-1b1b-4a25-91d3-db3cdd20e2cc.png
  • 常用节点类型: nodeType
《DOM探索之基础详解篇》笔记_第2张图片
c71689c8-5e78-4e79-8c9e-af32fcc2c210.png
  • nodeName 节点名称,nodeValue 节点值,attributes 获取属性
《DOM探索之基础详解篇》笔记_第3张图片
8592f28b-e69c-47b6-8f43-5a961bf34685.png

```


这是一个元素节点

```

二、DOM Ready

  • 页面加载时,有一个DOM节点构建的过程,当页面上所有的HTML都转换成了节点以后,就叫做DOM Ready(DOM树构建完毕)。
    • 浏览器通过渲染引擎将HTML标签解析编程DOM节点。
      • 渲染引擎的职责是:把请求到的内容显示到浏览器屏幕上。默认情况下渲染引擎可显示HTML、XML文档及图片。通过插件,其可显示其他类型的文档,如PDF等。

渲染引擎的渲染流程

  • 渲染:浏览器把请求到的HTML内容显示出来的过程。
  • 渲染引擎首先通过网络获得所请求文档的内容,通常以8k分块的方法来完成。
    • 之后的过程:(不包含浏览器加载外部资源的过程,如图片、脚本)
      1.解析HTML,构建DOM树(构建DOM节点)。
      2.构建渲染树(解析样式信息,包括外部的css文件、style标签中的样式)。渲染树由一些包含有各种属性的矩形组成,他们将会按照正确的顺序显 示到屏幕上。
      3.布局渲染树(布局DOM节点),执行布局的过程,将确定每个节点在屏幕上的确切坐标。
      4.绘制渲染树(绘制DOM节点,即遍历渲染树),使用UI后端层来绘制每个节点。
9c5c9a80-c81a-4265-b784-f9d192a937a0.png
  • Webkit主要渲染流程:

《DOM探索之基础详解篇》笔记_第4张图片
09de489c-0b25-4bde-af92-09746975f930.png

- 拓展阅读 浏览器内部工作原理

DOM Ready 的实现策略

《DOM探索之基础详解篇》笔记_第5张图片
54589b7c-179c-4f90-9b6e-a54a56ea920b.png
  • window.onload会完整加载页面后在触发。这些策略是DOM树加载完成就触发,无需等待其他东西的加载。
  • JQ就是这样的。
  • 自己来实现一个在标准和非标下模拟DOMContentLoaded的功能:
    function myReady(fn){
    //对于现代浏览器,对DOMContentLoaded事件的处理采用标准的事件绑定方式
    if ( document.addEventListener ) {
        document.addEventListener("DOMContentLoaded", fn, false);
    } else {
        IEContentLoaded(fn);
    }
    //IE模拟DOMContentLoaded
    function IEContentLoaded(fn) {
        var d = window.document;
        var done = false;
        //只执行一次用户的回调函数init()
        var init = function () {
            if (!done) {
                done = true;
                fn();
            }
        };
        (function () {
            try {
                // DOM树未创建完之前调用doScroll会抛出错误
                d.documentElement.doScroll('left');
            } catch (e) {
                //延迟再试一次~
                setTimeout(arguments.callee, 50);
                return;
            }
            // 没有错误就表示DOM树创建完毕,然后立马执行用户回调
            init();
        })();
        //监听document的加载状态
        d.onreadystatechange = function() {
            // 如果用户是在domReady之后绑定的函数,就立马执行
            if (d.readyState == 'complete') {
                d.onreadystatechange = null;
                init();
            }
        }
    }
    

}
```

  • 对比:
    var d = document;
      var msgBox = d.getElementById("showMsg");
      var imgs = d.getElementsByTagName("img");
      var time1 = null, time2 = null;
      myReady(function(){
          msgBox.innerHTML += "dom已加载!
    "; time1 = new Date().getTime(); msgBox.innerHTML += "时间戳:" + time1 + "
    "; }); window.onload = function(){ msgBox.innerHTML += "onload已加载!
    "; time2 = new Date().getTime(); msgBox.innerHTML += "时间戳:" + time2 + "
    "; msgBox.innerHTML +="domReady比onload快:" + (time2 - time1) + "ms
    ";

三、判断元素的节点类型

  • 判定方法:
    • isElement:判断是否为元素节点。
    • isHTML:判断是否为HTML文档的元素节点。
    • isXML:判断是否为XML文档的元素节点。
    • contains:判断两个节点的包含关系。

判断节点为元素节点 isElement

  • 简单版:
var isElement = function (el){
            return !!el && el.nodeType === 1;
        }
  • 完美版:
var isElement = function (obj) {
            if (obj && obj.nodeType === 1) {//先过滤最简单的
                if( window.Node && (obj instanceof Node )){ //如果是IE9,则判定其是否Node的实例
                    return true; //由于obj可能是来自另一个文档对象,因此不能轻易返回false
                }
                try {//最后以这种效率非常差但肯定可行的方案进行判定
                    testDiv.appendChild(obj);  // 不是元素节点,不能执行该步
                    testDiv.removeChild(obj);
                } catch (e) {
                    return false;
                }
                return true;
            }
            return false;
        }
  • 其他方案

判断节点为HTML和XML元素节点 isHTML isXML

  • HTML是XML的子集。
  • isXML:
    // Sizzle, jQuery自带的选择器引擎
        var isXML = function(elem) {
            var documentElement = elem && (elem.ownerDocument || elem).documentElement;
            return documentElement ? documentElement.nodeName !== "HTML" : false;
        };
        console.log(isXML(document.getElementById("test"))); // false
    
        // 但这样不严谨,因为XML的根节点,也可能是HTML标签,比如这样创建一个XML文档
        try {
            var doc = document.implementation.createDocument(null, 'HTML', null);
            console.log(doc.documentElement);
            console.log(isXML(doc));
        } catch (e) {
            console.log("不支持creatDocument方法");
        }
    
    // mootools的slick选择器引擎的源码:
        var isXML = function(document) {
            return (!!document.xmlVersion) || (!!document.xml) || (toString.call(document) == '[object XMLDocument]')
                    || (document.nodeType == 9 && document.documentElement.nodeName != 'HTML');
        };
    
        // 精简版
        var isXML = window.HTMLDocument ? function(doc) {
            return !(doc instanceof HTMLDocument);
        } : function(doc) {
            return "selectNodes" in doc;
        }
    
    • 用功能判断来实现:(佳)
    var isXML = function(doc) {
            return doc.createElement("p").nodeName !== doc.createElement("P").nodeName;
        }
    
  • isHTML:
    var isHTML = function(doc) {
            return doc.createElement("p").nodeName === doc.createElement("P").nodeName;
        }
    
    • isHTMLElement:
    var isElement = function (obj) {
            if (obj && obj.nodeType === 1) {//先过滤最简单的
                if( window.Node && (obj instanceof Node )){ //如果是IE9,则判定其是否Node的实例
                    return true; //由于obj可能是来自另一个文档对象,因此不能轻易返回false
                }
                try {//最后以这种效率非常差但肯定可行的方案进行判定
                    testDiv.appendChild(obj);
                    testDiv.removeChild(obj);
                } catch (e) {
                    return false;
                }
                return true;
            }
            return false;
        }
        var isHTMLElement(el){
           if(isElement){
              return isXML(el.ownerDocument);
           }
           return false;
        }
    

判断节点的包含关系 contains

  • 目前几乎所以浏览器都支持contains方法:

    
子节点内容
  • 自写全兼容版本方法:
    function fixContains(a, b) {
            try {
                while ((b = b.parentNode)){ // 找到内层节点的父节点,找不到便停止
                    if (b === a){ // b现在是父节点,若等于a,则说明a为父节点
                        return true;
                    }
                }
                return false;
            } catch (e) {
                return false;
            }
        }
    

四、继承层次与嵌套规则

DOM节点继承层次

  • 创建一个p元素,一共追溯了7层原型链,可见DOM是十分耗性能的 。
《DOM探索之基础详解篇》笔记_第6张图片
b2fbb735-0e38-499f-b14f-e3ebd4a6d97e.png
  • 创建一个文本,要追溯6层:


    《DOM探索之基础详解篇》笔记_第7张图片
    a82d56ad-ff35-454f-a0fc-923bb3ed43d0.png
  • 只是第一层的属性就有这么多,可见多用DOM会有多卡:
《DOM探索之基础详解篇》笔记_第8张图片
2f545974-67f5-4563-8bfe-755b7c003c48.png

HTML嵌套规则

  • HTML嵌套规则:HTML存在许多种类型的标签,有的标签下只允许特定的标签存在,这就叫HTML嵌套规则。
    • 不按HTML嵌套规则写,浏览器就不会正确解析,会将不符合嵌套规则的节点放到目标节点的下面,或者变为纯文本。
  • 块状元素和内联元素:
《DOM探索之基础详解篇》笔记_第9张图片
ebb804c4-878f-459d-8f9f-a2171c5f8235.png
《DOM探索之基础详解篇》笔记_第10张图片
0d8a5912-d889-48ff-9ec9-6c4956581d51.png
  • 块状元素和内联元素嵌套规则:
《DOM探索之基础详解篇》笔记_第11张图片
7b392fa5-1333-429f-af87-4a50be5be8d8.png
《DOM探索之基础详解篇》笔记_第12张图片
51064f6d-f23b-475b-9920-0681b3949049.png
《DOM探索之基础详解篇》笔记_第13张图片
69d68339-4832-455a-a3e1-5437cd2f659c.png
《DOM探索之基础详解篇》笔记_第14张图片
c781fd87-d163-44d0-9535-7ff23fc35d4d.png
《DOM探索之基础详解篇》笔记_第15张图片
1a0cec79-cfb9-4d2b-bab8-28a4a2eb95cb.png
  • 某些特殊元素嵌套规则:
《DOM探索之基础详解篇》笔记_第16张图片
04bc252f-b64c-4978-98fd-c2a4db902499.png
《DOM探索之基础详解篇》笔记_第17张图片
901f826b-01a7-46aa-94bc-ea83f6628e35.png
《DOM探索之基础详解篇》笔记_第18张图片
1e005ac5-1308-42a5-8702-7a271c3d7aa4.png
《DOM探索之基础详解篇》笔记_第19张图片
14b6c0bd-1d59-48c2-8242-5c9d3fc7f531.png
《DOM探索之基础详解篇》笔记_第20张图片
951be6f6-e5e9-42c5-b391-cd826ba1d13a.png

你可能感兴趣的:(《DOM探索之基础详解篇》笔记)