zoukankan      html  css  js  c++  java
  • (84)Wangdao.com第十八天_JavaScript 文档对象模型 DOM

    文档对象模型 DOM

    DOM 是 JavaScript 操作网页的接口,

    全称为“文档对象模型”(Document Object Model)。

    作用是将网页转为一个 JavaScript 对象,从而可以用脚本进行各种操作(比如增删内容)

    浏览器会根据 DOM 模型,将结构化文档(比如 HTML 和 XML)解析成一系列的节点,

    再由这些节点组成一个树状结构(DOM Tree)。所有的节点和最终的树状结构,都有规范的对外接口。

    DOM 只是一个接口规范,可以用各种语言实现。

     

    • 节点
      • DOM 的最小组成单位叫做节点(node)。
      • 文档的树形结构(DOM 树),就是由各种不同类型的节点组成。
      • 每个节点可以看作是文档树的一片叶子。

     

      • 节点的类型有七种:
        • 文档节点 Document:    整个文档树的顶层节点
        • 文档类型节点 DocumentType:    doctype标签(比如<!DOCTYPE html>)
        • 元素节点 Element:    网页的各种HTML标签(比如<body>、<a>等)
        • 属性节点 Attribute:    网页元素的属性(比如class="right")
        • 文本节点 Text:    标签之间或标签包含的文本
        • 注释节点 Comment:    注释(比如<!-- 页首部分 -->)
        • 文档片段节点 DocumentFragment:    文档的片段

     

    • 浏览器原生提供 document 节点,代表整个文档
      • 文档 document 的第一层只有一个节点,就是 HTML 网页的第一个标签 <html>,
        • 它构成了树结构的根节点(root node),其他 HTML 标签节点都是它的下级节点。

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

      • 根节点,其他节点都有三种层级关系
        • 父节点关系(parentNode):直接的那个上级节点
        • 子节点关系(childNodes):直接的下级节点
        • 同级节点关系(sibling):拥有同一个父节点的节点

     

      • DOM 提供操作接口,用来获取这三种关系的节点。
        • 子节点接口包括 firstChild()(第一个子节点)和 lastChild()(最后一个子节点)等属性
        • 同级节点接口包括 nextSibling()(紧邻在后的那个同级节点)和 previousSibling()(紧邻在前的那个同级节点)属性

     

    • 有 DOM 节点对象都继承了 Node 接口,拥有一些共同的属性和方法。这是 DOM 操作的基础
      • 属性
        • Node.prototype.nodeType
          • 返回一个整数值,表示节点的类型
            • document.nodeType    // 9
              document.nodeType === Node.DOCUMENT_NODE    // true    文档节点的 nodeType 属性等于 常量 Node.DOCUMENT_NODE
          • Node 对象定义了几个常量,对应这些类型值
            • 元素节点(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
            • 文档片断节点(DocumentFragment):11        对应常量 Node.DOCUMENT_FRAGMENT_NODE
              var node = document.documentElement.firstChild;
              if (node.nodeType === Node.ELEMENT_NODE) {    // 确定节点类型时,使用nodeType属性是常用方法
                  console.log('该节点是元素节点');
              }
        • Node.prototype.nodeName
          • 返回节点的名称
          • 不同节点的 nodeName 属性值如下
            • 元素节点(element):大写的标签名
            • 属性节点(attr):小写的属性的名称
            • 文本节点(text):#text
            • 注释节点(Comment):#comment
            • 文档节点(document):#document
            • 文档类型节点(DocumentType):文档的类型
            • 文档片断节点(DocumentFragment):#document-fragment
            • // HTML 代码如下
              // <div id="d1">hello world</div>
              
              var div = document.getElementById('d1');
              console.log(div.nodeName);    // "DIV"
        • Node.prototype.nodeValue
          • 返回一个字符串,表示当前节点本身的文本值,该属性可读写。
          • 只有文本节点(text)和注释节点(comment)有文本值,因此这两类节点的 nodeValue 可以返回结果,其他类型的节点一律返回 null
          • 同样的,也只有这两类节点可以设置 nodeValue 属性的值,其他类型的节点设置无效

     

        • Node.prototype.textContent
          • 返回当前节点和它的所有后代节点的文本内容
            • // HTML 代码为
              // <div id="divA">This is <span>some</span> text</div>
              
              document.getElementById('divA').textContent;    // This is some text
          • 自动忽略当前节点内部的 HTML 标签,返回所有文本内容
          • 自动对 HTML 标签转义。这很适合用于用户提供的内容
            • document.getElementById('foo').textContent = '<p>GoodBye!</p>';    // 会将<p>标签解释为文本,而不会当作标签处理。
          • 如果要读取整个文档的内容,可以使用 document.documentElement.textContent

     

        • Node.prototype.baseURI
          • 返回一个字符串,表示当前网页的绝对路径
          • 浏览器根据这个属性,计算网页上的相对路径的 URL。
            • // 当前网页的网址为
              // http://www.example.com/index.html
              document.baseURI    // "http://www.example.com/index.html"
          • 该属性为只读
          • 如果无法读到网页的 URL,baseURI属性返回null
          • 该属性的值一般由当前网址的 URL(即window.location属性)决定,
            • <base href="http://www.example.com/page.html">
              但是可以使用 HTML 的<base>标签,改变该属性的值

     

        • Node.prototype.ownerDocument
          • 返回当前节点所在的顶层文档对象,即 document 对象
            var d = p.ownerDocument;
            d === document    // true
            
            
            // document对象本身的ownerDocument属性,返回null

     

        • Node.prototype.nextSibling
          • 返回紧跟在当前节点后面的第一个同级节点。
          • 如果当前节点后面没有同级节点,则返回 null 
          • 注意,该属性还包括文本节点和注释节点(<!-- comment -->)。
            • 因此如果当前节点后面有空格,该属性会返回一个文本节点,内容为空格
          • 可以用来遍历所有子节点
            • var el = document.getElementById('div1').firstChild;
              
              while (el !== null) {
                  console.log(el.nodeName);
                  el = el.nextSibling;
              }

     

            • Node.prototype.previousSibling
                • 返回当前节点前面的、距离最近的一个同级节点
                • 如果当前节点前面没有同级节点,则返回 null
                • 注意,该属性还包括文本节点和注释节点。
                  • 因此如果当前节点前面有空格,该属性会返回一个文本节点,内容为空格

     

            • Node.prototype.parentNode
                • 返回当前节点的父节点。
                • 对于一个节点来说,它的父节点只可能是三种类型:
                    • 元素节点(element)
                    • 文档节点(document)
                    • 文档片段节点(documentfragment)
                • 利用 node.parentNode 属性 将node节点从文档里面移除
                  • if (node.parentNode) {
                        node.parentNode.removeChild(node);
                    }
                • 文档节点(document)和文档片段节点(documentfragment)的父节点都是null
                • 对于那些生成后还没插入 DOM 树的节点,父节点也是 null 

     

            • Node.prototype.parentElement
                • 返回当前节点的父元素节点
                • 如果当前节点没有父节点,或者父节点类型不是元素节点,则返回 null
                  • if (node.parentElement) {
                        node.parentElement.style.color = 'red';    // 父元素节点的样式设定了红色
                    }
            • Node.prototype.firstChild    Node.prototype.lastChild
                • 返回当前节点的 第一个子节点 / 最后一个子节点
                • 如果当前节点没有子节点,则返回 null
            • Node.prototype.childNodes
                • 返回一个类似数组的对象(NodeList 集合),成员包括当前节点的所有子节点
                  • var children = document.querySelector('ul').childNodes;
                    // 上面代码中,children 就是 ul 元素的所有子节点。


                    // 使用该属性,可以遍历某个节点的所有子节点。

                    var div = document.getElementById('div1');
                    var children = div.childNodes;

                    
                    

                    for (var i = 0; i < children.length; i++) {
                        // ...
                    }

                     
                • 文档节点(document)就有两个子节点:文档类型节点(docType)HTML 根元素节点
                  • var children = document.childNodes;
                    for (var i = 0; i < children.length; i++) {
                        console.log(children[i].nodeType);
                    }
                    // 10
                    // 1
                    // 上面代码中,文档节点的第一个子节点的类型是10(即文档类型节点),第二个子节点的类型是1(即元素节点)。
                • 注意:
                  • 除了元素节点,childNodes 属性的返回值还包括文本节点和注释节点。
                  • 如果当前节点不包括任何子节点,则返回一个空的 NodeList 集合。
                  • 由于 NodeList 对象是一个动态集合,一旦子节点发生变化,立刻会反映在返回结果之中。

     

            • Node.prototype.isConnected
                • 表示当前节点是否在文档之中,返回一个布尔值
                  var test = document.createElement('p');
                  test.isConnected;     // false
                  
                  document.body.appendChild(test);
                  test.isConnected;     // true

                  脚本生成的节点,没有插入文档之前,isConnected 属性返回 false,插入之后返回 true

     

      • 方法
        • Node.prototype.appendChild()
          • 接受一个节点对象作为参数,将其作为最后一个子节点,插入当前节点。
          • 该方法的返回值就是插入文档的子节点。
          • 如果参数节点是 DOM 已经存在的节点
            • appendChild方法会将其从原来的位置,移动到新位置
          • var element = document.createElement('div').appendChild(document.createElement('b'));

            上面代码的返回值是<b></b>,而不是<div></div>

          • 如果 appendChild 方法的参数是 DocumentFragment 节点
            • 那么插入的是 DocumentFragment 的所有子节点,而不是 DocumentFragment 节点本身。
            • 返回值是一个空的 DocumentFragment 节点
        • Node.prototype.hasChildNodes()
          • 返回一个布尔值,表示当前节点是否有子节点
            • var foo = document.getElementById('foo');
              
              if (foo.hasChildNodes()) {    // 如果foo节点有子节点,就移除第一个子节点
                      foo.removeChild(foo.childNodes[0]);
              }
          • 子节点包括所有类型的节点
            • 并不仅仅是元素节点
            • 哪怕节点只包含一个空格,hasChildNodes 方法也会返回 true 
        • Node.prototype.cloneNode()
          • 用于克隆一个节点。
          • 它接受一个布尔值作为参数,表示是否同时克隆子节点。
          • 它的返回值是一个克隆出来的新节点
          • 注意:
            • 克隆一个节点,会拷贝该节点的所有属性,但是会丧失 addEventListener方法 和 on-属性(即node.onclick = fn)
            • 该方法返回的节点不在文档之中,即没有任何父节点,必须使用诸如 Node.appendChild() 这样的方法添加到文档之中
            • 克隆一个节点之后,DOM 有可能出现两个有相同id属性(即id="xxx")的网页元素,这时应该修改其中一个元素的id属性。
            • 如果原节点有name属性,可能也需要修改
        • Node.prototype.insertBefore()
          • 用于将某个节点插入父节点内部的指定位置
            • var insertedNode = parentNode.insertBefore(newNode, referenceNode);
          • 第一个参数是所要插入的节点 newNode
          • 第二个参数是父节点 parentNode 内部的一个子节点 referenceNode
            • newNode 将插在 referenceNode 这个子节点的前面
            • 返回值是插入的新节点 newNode
          • 如果 insertBefore() 方法的第二个参数为 null,则新节点将插在当前节点内部的最后位置,即变成最后一个子节点
            • var p = document.createElement('p');
              document.body.insertBefore(p, null);     // p 将成为 document.body 的最后一个子节点
          • 注意:
            • 如果所要插入的节点是当前 DOM 现有的节点,则该节点将从原有的位置移除,插入新的位置。
            • 由于不存在 insertAfter 方法,如果新节点要插在父节点的某个子节点后面,可以用 insertBefore 方法结合 nextSibling 属性模拟
              • parent.insertBefore(s1, s2.nextSibling);

                如果要将 s1 插在 s2 的后面,则插在 s2 后面一个节点的前面即可

            • 如果要插入的节点是 DocumentFragment 类型,那么插入的将是 DocumentFragment 的所有子节点,而不是 DocumentFragment 节点本身。返回值将是一个空的 DocumentFragment 节点
        • Node.prototype.removeChild()
          • 接受一个子节点作为参数,用于从当前节点移除该子节点。
          • 返回值是移除的子节点。
            • var divA = document.getElementById('A');
              divA.parentNode.removeChild(divA);    // 移除了divA节点,这个方法是在   divA 的父节点上  调用的,不是在 divA 上调用的
          • 被移除的节点依然存在于内存之中,但不再是 DOM 的一部分。
            • 所以,一个节点移除以后,依然可以使用它,比如插入到另一个节点下面。
          • 如果参数节点不是当前节点的子节点,removeChild 方法将报错。
            • 移除当前节点的所有子节点
              var element = document.getElementById('top');
              while (element.firstChild) {    // 确定当前元素还有子节点
                  element.removeChild(element.firstChild);
              }
        • Node.prototype.replaceChild()
          • 用于将一个新的节点,替换当前节点的某一个子节点
              • var replacedNode = parentNode.replaceChild(newChild, oldChild);
          • 第一个参数 newChild 是用来替换的新节点
          • 第二个参数 oldChild 是将要替换走的子节点。返回值是替换走的那个节点 oldChild
            • var divA = document.getElementById('divA');
              var newSpan = document.createElement('span');
              newSpan.textContent = 'Hello World!';
              divA.parentNode.replaceChild(newSpan, divA);

              将指定节点 divA 替换走

        • Node.prototype.contains()
          • 返回一个布尔值,表示参数节点是否满足以下三个条件之一
            • 参数节点为当前节点
            • 参数节点为当前节点
            • 参数节点为当前节点
              • document.body.contains(node);    // 检查参数节点node,是否包含在当前文档之中
        • Node.prototype.compareDocumentPosition()
          • 用法与contains方法完全一致,返回一个七个比特位的二进制值,表示参数节点与当前节点的关系

          • // HTML 代码如下
            // <div id="mydiv">
            //   <form><input id="test" /></form>
            // </div>
            
            var div = document.getElementById('mydiv');
            var input = document.getElementById('test');
            
            div.compareDocumentPosition(input);    // 20
            input.compareDocumentPosition(div);    // 10
        • Node.prototype.isEqualNode()    Node.prototype.isSameNode()
          • isEqualNode() 方法返回一个布尔值,用于检查两个节点是否相等
          • 所谓相等的节点,指的是
            • 两个节点的类型相同、属性相同、子节点相同。
              var p1 = document.createElement('p');
              var p2 = document.createElement('p');
              
              p1.isEqualNode(p2) // true
          • isSameNode() 方法返回一个布尔值,表示两个节点是否为同一个节点。
            var p1 = document.createElement('p');
            var p2 = document.createElement('p');
            
            p1.isSameNode(p2);    // false
            p1.isSameNode(p1);    // true
        • Node.prototype.normalize()
          • 用于清理当前节点内部的所有文本节点(text)
            • 它会去除空的文本节点,
            • 并且将毗邻的文本节点合并成一个
            • 也就是说不存在空的文本节点,以及毗邻的文本节点。
          • var wrapper = document.createElement('div');
            
            wrapper.appendChild(document.createTextNode('Part 1 '));
            wrapper.appendChild(document.createTextNode('Part 2 '));
            
            wrapper.childNodes.length;    // 2
            wrapper.normalize();
            wrapper.childNodes.length;    // 1

            使用normalize方法之后,两个文本子节点被合并成一个。。。该方法是 Text.splitText 的逆方法,可以查看《Text 节点对象》一章,了解更多内容。

        • Node.prototype.getRootNode()
          • 返回当前节点所在文档的根节点,与 ownerDocument属性 的作用相同

     

     

     

     

     

    --------小尾巴 ________一个人欣赏-最后一朵颜色的消逝-忠诚于我的是·一颗叫做野的心.决不受人奴役.怒火中生的那一刻·终将结束...
  • 相关阅读:
    PAT (Advanced Level) 1114. Family Property (25)
    PAT (Advanced Level) 1113. Integer Set Partition (25)
    PAT (Advanced Level) 1112. Stucked Keyboard (20)
    PAT (Advanced Level) 1111. Online Map (30)
    PAT (Advanced Level) 1110. Complete Binary Tree (25)
    PAT (Advanced Level) 1109. Group Photo (25)
    PAT (Advanced Level) 1108. Finding Average (20)
    PAT (Advanced Level) 1107. Social Clusters (30)
    PAT (Advanced Level) 1106. Lowest Price in Supply Chain (25)
    PAT (Advanced Level) 1105. Spiral Matrix (25)
  • 原文地址:https://www.cnblogs.com/tianxiaxuange/p/9818411.html
Copyright © 2011-2022 走看看