zoukankan      html  css  js  c++  java
  • DOM基础+domReady+元素节点类型判断

    DOM节点类型  nodeType

    element  1    Node.ELEMENT_NODE   元素节点

    attr  2   Node.ATTRIBUTE_NODE  属性节点

    text  3    Node.TEXT_NODE   文本节点(标签之间的空白区域也属于文本节点)

    comment   8     Node.COMMENT_NODE   注释节点

    document   9     Node.DOCUMENT_NODE   文档节点(所有文档之上,即一个页面中最最前面的位置,在文档定义的前面)

    documentType   10    Node.DOCUMENT_TYPE_NODE   文档类型节点(DOCTYPE)

    documentFragment   11    Node.DOCUMENT_FRAGMENT_NODE  文档片段节点(不属于文档树,是最小片段,可以作为临时占位符,将它插入文档时,只会插入它的子孙元素,而不是它本身)

    注意:IE8及以下没有node,使用常量来判断nodeType会报错:“Node”未定义

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            body{
                width:100%;
                height:100%;
            }
        </style>
    
    </head>
    <body>
        <div id="container"></div>
        <script>
            window.onload=function(){
    
                var container=document.getElementById("container");
                if(container.nodeType==Node.ELEMENT_NODE){
                    alert("是元素节点");
                }
            }    
        </script>
    </body>
    </html>

     因此不建议使用常量来判断,建议使用数值

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            body{
                width:100%;
                height:100%;
            }
        </style>
    
    </head>
    <body>
        <div id="container"></div>
        <script>
            window.onload=function(){
    
                var container=document.getElementById("container");
                // if(container.nodeType==Node.ELEMENT_NODE){
                //     alert("是元素节点");
                // }
                if(container.nodeType==1){
                    alert("是元素节点");
                }
            }    
        </script>
    </body>
    </html>

     nodeName  节点名称

    nodeValue  节点值

    .attributes 保存元素的所有属性,可以使用数组下标访问某一个具体的属性

    .chilsNodes 获取元素的所有子节点,可以使用数组下标访问某一个具体的属性

    document.doctype  获取文档类型节点

    document.createDocumentFlagment()  创建文档片段

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            body{
                width:100%;
                height:100%;
            }
        </style>
    
    </head>
    <body>
        <!-- 这是一段注释哈 -->
        <div id="container">这是里面的文本鸭</div>
        <script>
            window.onload=function(){
    
                var container=document.getElementById("container");
                console.log("元素节点:"+container.nodeName+"/"+container.nodeValue);//元素节点:DIV/null
                var attr=container.attributes[0];//获取元素的第一个属性
                console.log("属性节点:"+attr.nodeName+"/"+attr.nodeValue);//属性节点:id/container
                var text=container.childNodes[0];//获取元素的第一个子元素节点
                console.log("文本节点:"+text.nodeName+"/"+text.nodeValue);//文本节点:#text/这是里面的文本鸭
                var comment=document.body.childNodes[1];//获取body元素的第二个子元素节点(第一个子元素节点是空白文本节点)
                console.log("注释节点:"+comment.nodeName+"/"+comment.nodeValue);//注释节点:#comment/ 这是一段注释哈 
                var doctype=document.doctype;//获取body元素的第二个子元素节点(第一个子元素节点是空白文本节点)
                console.log("文档类型节点:"+doctype.nodeName+"/"+doctype.nodeValue);//文档类型节点:html/null
                var docFragment=document.createDocumentFragment();//获取body元素的第二个子元素节点(第一个子元素节点是空白文本节点)
                console.log("文档片段节点:"+docFragment.nodeName+"/"+docFragment.nodeValue);//文档片段节点:#document-fragment/null
            }    
        </script>
    </body>
    </html>

     当script脚本在DOM元素之前,会无法获取到DOM元素

    因为把js代码放在head中,代码顺序执行,当页面在浏览器中打开时,会先执行js代码,再执行body里面的dom结构。如果js执行时要获取body中的元素,那么就会报错,因为页面的结构还没有加载进来。

    可以使用window.onload解决

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            body{
                width:100%;
                height:100%;
            }
        </style>
        <script>
            window.onload=function(){
    
                var container=document.getElementById("container");
                console.log(container);
            }    
        </script>
    </head>
    <body>
        <!-- 这是一段注释哈 -->
        <div id="container">这是里面的文本鸭</div>
    
    </body>
    </html>

    window.onload缺点:等待DOM树的加载和外部资源全部加载完成

    如果页面引用了很多外部资源,会导致加载慢,影响用户体验


    最佳解决方案,jquery的$(document).ready()

    此处使用原生js仿写该方法


    DOMContentLoaded  加载完dom树,但还没有开始加载外部资源

    IE不支持该方法,使用:document.documentElement.doScroll("left")


    监听document的加载状态  document.onreadystatechange

    document加载完成  document.readyState=="complete"

    arguments.callee  调用函数自身

    自己写的DomReady.js

    function myReady(fn){
    
        /*
        现代浏览器操作
        */
        if(document.addEventListener){
            //现代浏览器操作
            document.addEventListener("DOMContentLoaded",fn,false);//false表示在冒泡阶段捕获
        }else{
            //IE环境操作
            IEContentLoaded(fn);
        }
    
        /*
        IE环境操作
        */
        function IEContentLoaded(fn){
    
            // init()--保证fn只调用一次
            var loaded=false;
            var init=function(){
                if(!loaded){
                    loaded=true;
                    fn();
                }
            }
    
            // 如果DOM树加载还没完成,就不停尝试
            (function(){
                try{
                    // 如果DOM树加载还没完成,会抛出异常
                    document.documentElement.doScroll("left");
                }catch(e){
                    // 尝试失败,则再次尝试
                    setTimeout(arguments.callee,50);
                    return;//实现递归
                }
                //如果没有抛出异常,则立刻执行init()
                init();
                
            })();
    
            // DOM树加载完成之后,调用init()方法
            document.onreadystatechange=function(){
                if(document.readyState=="complete"){
                    document.onreadystatechange=null;//清除监听事件
                    init();
                }
            }
        }
    }

    调用该js

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            body{
                width:100%;
                height:100%;
            }
        </style>
        <script src="DomReady.js"></script>
        <script>
            myReady(function(){
                var container=document.getElementById("container");
                console.log(container);
            });
        </script>
    </head>
    <body>
        <!-- 这是一段注释哈 -->
        <div id="container">这是里面的文本鸭</div>
    
    </body>
    </html>

    实现各浏览器都能成功获取到~

    下面来真实感受下window.onload 和domReady的区别!!!

    使用多张大图图片来模拟加载时长

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            body{
                width:100%;
                height:100%;
            }
        </style>
        <script src="DomReady.js"></script>
    
    </head>
    <body>
        <!-- 这是一段注释哈 -->
        <div id="container">这是里面的文本鸭</div>
        <img src="source/cat.jpg">
        <img src="source/cat.jpg">
        <img src="source/cat.jpg">
        <img src="source/cat.jpg">
        <img src="source/cat.jpg">
        <img src="source/cat.jpg">
        <img src="source/cat.jpg">
        <img src="source/cat.jpg">
        <img src="source/cat.jpg">
        <img src="source/cat.jpg">
        <img src="source/cat.jpg">
        <img src="source/cat.jpg">
        <img src="source/cat.jpg">
        <img src="source/cat.jpg">
        <img src="source/cat.jpg">
        <img src="source/cat.jpg">
        <img src="source/cat.jpg">
        <img src="source/cat.jpg">
    
        <script>
    
            myReady(function(){
                alert("domReady!");
                domready=new Date().getTime();
            });
    
            window.onload=function(){
                alert("windowLoaded!");
                windowload=new Date().getTime();
            }
    
        </script>
    </body>
    </html>

    发现先弹出domReady

    等到图片加载完成之后,才弹出windowLoaded

    证实windowLoaded耗时比较久


    元素节点的类型判断

    isElement() 判断是否是元素节点

    isHTML() 判断是否是html文档的元素节点

    isXML() 判断是否是xml文档的元素节点

    contains()  判断元素节点之间是否是包含关系

    .nextSibling  获取元素的兄弟节点

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            body{
                width:100%;
                height:100%;
            }
        </style>
        <script src="DomReady.js"></script>
    
    </head>
    <body>
        
        <div id="container">这是里面的文本鸭</div><!-- 这是一段注释哈 -->
    
        <script>
    
            myReady(function(){
                
                function isElement(el){
                    return !!el && el.nodeType===1;
                }
    
                console.log(isElement(container));
                console.log(isElement(container.nextSibling));
            });
    
        </script>
    </body>
    </html>

    该方法有一个Bug,即如果有一个对象设置了nodeType属性,会导致判断错误

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            body{
                width:100%;
                height:100%;
            }
        </style>
        <script src="DomReady.js"></script>
    
    </head>
    <body>
        
        <div id="container">这是里面的文本鸭</div><!-- 这是一段注释哈 -->
    
        <script>
            
            myReady(function(){
                
                function isElement(el){
                    return !!el && el.nodeType===1;
                }
    
                var obj={
                    nodeType:1
                }
                console.log(isElement(obj));//true
            });
    
        </script>
    </body>
    </html>

    isXML() 最严谨的写法

    .createElement() 创建元素

    如果不区分大小写,则为html文档的元素节点;

    如果区分大小写,则为xml文档的元素节点

    .ownerDocument返回元素自身的文档对象

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            body{
                width:100%;
                height:100%;
            }
        </style>
        <script src="DomReady.js"></script>
    
    </head>
    <body>
        
        <div id="container">这是里面的文本鸭</div><!-- 这是一段注释哈 -->
    
        <script>
            
            myReady(function(){
                // 判断是否是元素节点
                function isElement(el){
                    return !!el && el.nodeType==1;
                }
                // 判断是否是xml文档
                function isXML(el){
                    return el.createElement("p").nodeName!==el.createElement("P").nodeName;
                }
                // 判断是否是html文档
                function isHTML(el){
                    return el.createElement("p").nodeName===el.createElement("P").nodeName;
                }
                // 判断是否是html文档的元素节点
                function isHTMLNode(el){
                    if(isElement(el)){
                        return isHTML(el.ownerDocument);
                    }
                    return false;
                }
                console.log(isXML(document));//false
                console.log(isHTML(document));//true
                console.log(isHTMLNode(container));//true
            });
    
        </script>
    </body>
    </html>

    .containers 判断某个节点是否包含另一个节点

    谷歌浏览器表现正常,而IE浏览器要求两个节点都必须是元素节点

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            body{
                width:100%;
                height:100%;
            }
        </style>
        <script src="DomReady.js"></script>
    
    </head>
    <body>
        
        <div class="parent" id="parent">
            <div class="child" id="child">这是文本节点</div>
        </div>
    
        <script>
            
            myReady(function(){
                var parent=document.getElementById("parent");
                var child=document.getElementById("child");
                console.log(parent.contains(child));//true
    
                var text=child.childNodes[0];
                console.log(parent.contains(text));//谷歌浏览器true,IE浏览器为false
            });
    
        </script>
    </body>
    </html>

    接下来给出兼容性写法

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            body{
                width:100%;
                height:100%;
            }
        </style>
        <script src="DomReady.js"></script>
    
    </head>
    <body>
        
        <div class="parent" id="parent">
            <div class="child" id="child">这是文本节点</div>
        </div>
    
        <script>
            
            myReady(function(){
                var parent=document.getElementById("parent");
                var child=document.getElementById("child");
                console.log(parent.contains(child));//true
    
                var text=child.childNodes[0];
                console.log(parent.contains(text));//谷歌浏览器true,IE浏览器为false
    
                function fixContains(pNode,cNode){
                    try{
                        while(cNode=cNode.parentNode){
                            if(pNode===cNode) return true;
                        }
                        return false;
                    }catch(e){
                        return false;
                    }
                }
                console.log(fixContains(parent,text));//谷歌浏览器true,IE浏览器为true
            });
    
        </script>
    </body>
    </html>

    在所有浏览器里都能返回true,哪怕不是元素节点

  • 相关阅读:
    linux环境下,使用Navicat连接mysql时,提示本地IP无法连接虚拟环境下的mysql解决方案
    数组-(Zero Sum Subarray)返回数组中和为某个数的子串数组
    hash、hashlib使用
    优先队列
    Jensen 不等式
    ML-集成学习:AdaBoost、Bagging、随机森林、Stacking(mlxtend)、GBDT、XGBoost、LightGBM、CatBoost原理推导及实现
    scipy.optimize优化器的各种使用
    RL-马尔科夫决策过程(MDP)-原理及实现
    ML-sklearn参数随机优化:GridSearchCV、RandomizedSearchCV、hyperopt
    5.matplotlib绘制-meshgrid区域图-可视化ML
  • 原文地址:https://www.cnblogs.com/chenyingying0/p/12269336.html
Copyright © 2011-2022 走看看