(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属性 的作用相同

 

 

 

 

 

--------小尾巴 ________一个人欣赏-最后一朵颜色的消逝-忠诚于我的是·一颗叫做野的心.决不受人奴役.怒火中生的那一刻·终将结束...
原文地址:https://www.cnblogs.com/tianxiaxuange/p/9818411.html