dom总结:节点层次

作者: 我不是大熊 | 来源:发表于2018-02-03 14:04 被阅读0次

HTML可以描绘成一个多层节点构成的结构,文档节点是每个文档的根节点,<html>元素被称之为文档元素,是文档的最外层元素。不同的标记用不同的节点来表示。

1. Node类型

Node接口在Javascript中是作为Node类型实现的,除了IE之外,在其他所有浏览器中都可以访问到这个类型。而Javascript的所有节点类型都继承自Node类型。

  • 1.1nodeType属性

表明节点类型:1.Node.ELEMENT_NODE,2.Node.ATTRIBUTE_NODE,3.Node.TEXT_NODE,4.Node.CDATA_SECTION_NODE,5.Node.ENTITY_REFERENCE_NODE,6.Node.ENTITY_NODE,7.Node.PROCESSING_INSTRUCTION_NODE,8.Node.COMMENT_NODE,9.Node.DOCUMENT_NODE,10.Node.DOCUMENT_TYPE_NODE,11.Node.DOCUMENT_FRAGMENT_NODE,12.Node.NOTATION_NODE

    var btn1 = document.getElementsByClassName('btn1')[0];
    if(btn1.nodeType == 1){
        console.log('这是元素节点');
    }
  • 1.2nodeName 和 nodeValue 属性
    //对于元素节点,nodeName中保存的始终都是元素的标签名,而nodeValue的值则始终为null
    console.log(btn1.nodeName);//这里是一个按钮,所以打印BUTTON
    console.log(btn1.nodeValue);
  • 1.3节点关系
    • childNodes:NodeList 对象,NodeList 对象是类数组对象,用于保存一组有序的节点。
    html:
    <ul class="ul-list"><li>第一行</li><li>第二行</li><li>第三行</li></ul>

    js:
    var ulList = document.getElementsByClassName('ul-list')[0];
    console.log(ulList.childNodes);
    var first = ulList.childNodes[0];
    console.log(first);
    var last = ulList.childNodes[ulList.childNodes.length-1];
    console.log(last);

    //hasChildNodes()方法判断是否有子节点
    console.log(ulList.hasChildNodes());
    //ownerDocument返回所在的文档,而且每个节点只能在一个文档中
    console.log(ulList.ownerDocument);
  • parentNode:父节点
//打印ulList
console.log(last.parentNode);
  • previousSibling和nextSibling
    console.log(second.previousSibling);//打印第三行
    console.log(second.nextSibling);//打印第一行
    console.log(last.nextSibling);//打印null
  • firstChild和lastChild
  console.log(ulList.firstChild);//打印第一行
  console.log(ulList.lastChild);//打印第三行
  • 1.4操作节点
    • appendChild()
    html:
    <div class="div-con">
        <p>div中的第一行</p>
        <p class="second-p">div中的第二行</p>
        <p>div中的第三行</p>
    </div>

    js:
    var div1 = document.getElementsByClassName('div-con')[0];
    var p = document.createElement("p");
    p.innerText = '这是新创建的段落';
    //返回值是被添加的子节点
    var appendP = div1.appendChild(p);
    console.log(appendP == p);
    //如果传入到 appendChild()中的节点已经是文档的一部分,那么就是将该节点从原来的位置转移到新位置
    var secondP = document.getElementsByClassName('second-p')[0];
    div1.appendChild(secondP);
  • insertBefore()
    var div1 = document.getElementsByClassName('div-con')[0];
    var secondP = document.getElementsByClassName('second-p')[0];
    var p = document.createElement("p");
    p.innerText = '这是新创建的段落';
    //insertBefore:指定放到某个子节点之前,如果第二个参数传null,则新节点会被放在最后
    div1.insertBefore(p,secondP);
  • replaceChild()
    var div1 = document.getElementsByClassName('div-con')[0];
    var secondP = document.getElementsByClassName('second-p')[0];
    var p = document.createElement("p");
    p.innerText = '这是新创建的段落';
    //replaceChild:替换子节点
    div1.replaceChild(p,secondP);
  • removeChild()
    var div1 = document.getElementsByClassName('div-con')[0];
    var secondP = document.getElementsByClassName('second-p')[0];
    //removeChild:删除子节点
    div1.removeChild(secondP);
  • 1.5其他方法
    • cloneNode()
    var ulList = document.getElementsByClassName('ul-list')[0];
    var div1 = document.getElementsByClassName('div-con')[0];
    //cloneNode:传是否深复制的参数,true为深复制(把子节点也复制过来),false则否.
    //事件处理程序不会被复制,但IE有bug,会复制事件处理程序,所以复制之前最好把事情处理程序去掉
    var cloneList = ulList.cloneNode(true);
    console.log(cloneList);
    //注意的是,cloneNode完之后必须要为它指定父节点,不然它无法显示
    div1.appendChild(cloneList);
  • normalize
    这个方法唯一的作用就是处理文档树中的文本节点。 由于解析器的实现或 DOM 操作等原因,可能会出现文本节点不包含文本,或者接连出现两个文本节点 的情况。当在某个节点上调用这个方法时,就会在该节点的后代节点中查找上述两种情况。如果找到了 空文本节点,则删除它;如果找到相邻的文本节点,则将它们合并为一个文本节点。

2.Document类型

在浏览器中,document对象是window的属性,可以直接访问.而document对象是HTMLDocument类型的实例(HTMLDocument类型继承自Document类型),document对象表示整个文档。

  • 2.1文档的子节点
    console.log(document);
    //为9
    console.log(document.nodeType);
    //为:#document
    console.log(document.nodeName);
    //为null
    console.log(document.nodeValue);
    //为null
    console.log(document.parentNode);
    //为null
    console.log(document.ownerDocument);
    //打印子节点:子节点可能有DocumentType,Element,ProcessingIn-struction,Comment.
    //兼容性的问题是不同浏览器对于出现在<html></html>以外的注释Comment是否加入到document的子节点中不一致
    console.log(document.childNodes);
    var docuChild = document.childNodes;
    for(var i=0,len=docuChild.length;i<len;i++){
        console.log(docuChild[i].nodeType);
    }
    //各浏览器对于doctype的支持不一致
    console.log(document.doctype);
    //常用的话是document的以下属性:
    //documentElement指向<html>元素
    console.log(document.documentElement);
    //指向<body>元素
    console.log(document.body);
  • 2.2文档信息
//有一些属性是Document类型没有,是HTMLDocument类型才有的属性:
    //标题
    console.log(document.title);
    //可以修改文档标题
    document.title = 'bom学习';
    //URL:完整URL地址,domain:域名,referrer:来源页面的URL(如果没有就是空字符串)
    console.log(document.URL);
    console.log(document.domain);
    console.log(document.referrer);
    //可以设置domain:当页面中包含来自其他子域的框架或内嵌框架时,能够设置document.domain就非常方便了。
    //由于跨域安全限制,来自不同子域的页面无法通过 JavaScript 通信。
    //而通过将每个页面的 document.domain 设置为相同的值,
    //这些页面就可以互相访问对方包含的 JavaScript 对象了
    //不能将这个属性设置为URL中不包含的域
    //假设页面来自 p2p.wrox.com 域
    document.domain = "wrox.com"; // 成功
    document.domain = "nczonline.net"; // 出错!
    //浏览器对domain属性还有一个限制,即如果域名一开始是“松散的”(loose),那么不能将它再设置为“紧绷的”(tight)
    //假设页面来自于 p2p.wrox.com 域
    document.domain = "wrox.com"; //松散的(成功)
    document.domain = "p2p.wrox.com"; //紧绷的(出错!)
  • 2.3查找元素
    • getElementById():返回文档中指定id特性的元素,只返回文档中第一次出现指定id的元素。兼容性:①IE8 及较低版本不区分 ID 的大小写,其他浏览器都会区分;②IE7及更低版本:name 特性与给定 ID 匹配的表单元素(<input>、 <textarea>、<button>及<select>)也会被该方法返回(所以要避免name跟id相同的值)。
    • getElementsByTagName():返回的是包含零或多个元素的 NodeList,在 HTML 文档中,这个方法会返回一个 HTMLCollection 对象。
   //将HTMLCollection对象保存在lis变量中
   var imgs = document.getElementsByTagName('img');
   console.log(imgs);
   //获取其中某个元素:①item()方法
   console.log(imgs.item(0));
   //②类似数组传个index:底层调用了item()方法
   console.log(imgs[0]);
   //③使用这个方法可以通过元素的name特性取得集合中的项
   console.log(imgs.namedItem('shop'));
   //④HTMLCollection 还支持按名称访问项:底层调用了namedItem()方法
   console.log(imgs["changephone"]);
   //如果传入*当做tagName的话,会返回所有的元素
   var allEles = document.getElementsByTagName("*");
  • getElementsByName():HTMLDocument类型才有的方法.
    这个方法会返回带有给定 name 特性的所有元素,也是HTMLCollectioin集合.
html:
<div>
    <input type="radio" name="fruit" id="apple" value="苹果">
    <label for="apple">苹果</label>
    <input type="radio" name="fruit" id="pear" value="雪梨">
    <label for="pear">雪梨</label>
    <input type="radio" name="fruit" id="banana" value="香蕉">
    <label for="banana">香蕉</label>
</div>

js:
    var radios = document.getElementsByName('fruit');
    console.log(radios);
  • 2.4特殊集合

除了属性和方法,document 对象还有一些特殊的集合。这些集合都是 HTMLCollection 对象, 为访问文档常用的部分提供了快捷方式:

html:
<a>百度</a>
<a href="http://piaoshu.org" name="piaoshu">漂书</a>
<a href="http://taobao.com">淘宝</a>

js:
    //包含文档中所有的<form>元素
    console.log(document.forms);
    //包含文档中所有的<img>元素
    console.log(document.images);
    //包含文档中所有带有name特性的<a>元素
    console.log(document.anchors);//1个
    //包含文档中所有带 href 特性的<a>元素
    console.log(document.links);//2个
    //包含文档中所有的<a>元素
    console.log(document.getElementsByTagName('a'));//3个
  • 2.5DOM一致性检测

DOM分为多个级别,也包含多个部分,所以一致性检测有需要:

   //参数:要检测的 DOM 功能的名称及版本号,如果实现了就返回true
   console.log(document.implementation.hasFeature('HTML','2.0'));
Snip20180125_31.png
但hasFeature的返回有时会不准确(浏览器可能是返回了true但并未全部实现),所以大多数情况下推荐使用能力检测.
  • 2.6文档写入
    //文档写入:writeln和write的区别是writeln在写入之后加了一个'\n'符
    //还可以写入script文件等等,注意对"和/script的转义
    document.write("<strong>" + (new Date()).toLocaleString() + "</strong>");
    document.writeln("<img src='../../weixin/images/category@2x.png'>");
    document.write("<script type=\"text/javascript\" src=\"dom1.js\"><\/script>");
    //如果onload之中写入会覆盖文档的原有内容
    window.onload = function () {
        document.write('覆盖性写入');
    }
    //方法 open()和 close()分别用于打开和关闭网页的输出流

3.Element类型

    var btn1 = document.getElementsByClassName('btn1')[0];
    //为1
    console.log(btn1.nodeType);
    //为null
    console.log(btn1.nodeValue);
    //BUTTON(是大写)
    console.log(btn1.nodeName);
    console.log(btn1.tagName);
    //要比较标签名的话直接转化为小写比较会有通用性(HTML和XML中)
    console.log(btn1.tagName.toLowerCase() == 'button');
  • 3.1 HTML元素

HTML元素:用HTMLElement类型表示,不是直接通过这个类型,也是通过它的子类型来表示,如HTMLDivElement,HTMLButtonElement,HTMLImageElement等等.HTMLElement直接继承自Element类型并添加了一些属性:①id:元素在文档中的唯一标识符,②className:与元素的class特性对应,③title:有关元素的附加说明信息,一般通过工具提示条显示出来,④lang:元素内容的语言代码,很少使用,⑤dir:语言的方向,ltr左到右,rtl右到左,很少使用.

获取属性:

    var btn1 = document.getElementById('btn1');
    console.log(btn1.id);
    console.log(btn1.className);
    console.log(btn1.title);
    console.log(btn1.lang);
    console.log(btn1.dir);
    console.log(btn1.onclick);
    console.log(btn1.style);

设置属性:

    btn1.id = 'newBtn1';
    btn1.title = '设置的title属性';
  • 3.2取得特性

getAttribute()方法:参数是特性名称.而特性并不等于属性,这里做一个分类:

  • ①:公认特性(标准特性):就是指上面所述的.标准特性的特点:BOM对象会为标准特性创建相应名称的属性(class例外,对应属性名称是className,因为class是关键词).访问属性和特性获取到的内容一样,有两个特殊:onclick和style,属性返回对象,特性返回字符串(IE7及更早版本除外,特性也返回对象)
    var btn1 = document.getElementById('btn1');
    console.log(btn1.getAttribute('id'));
    console.log(btn1.getAttribute('title'));
    console.log(btn1.getAttribute('class'));
    console.log(btn1.getAttribute('onclick'));
    console.log(btn1.getAttribute('style'));
  • 自定义特性(特性名称不区分大小写)(自定义特性一般加data-前缀):对应自定义特性,只有IE才会把它以属性的形式添加到DOM对象,其他浏览器则不会,一般使用getAttribute()获取
console.log(btn1.getAttribute('data-index'));

所以总结起来就是:以编程的方式操纵DOM时,常使用对象的属性,对于自定义特性才使用getAttribute().

  • 3.3设置特性
    //设置特性:
    btn1.setAttribute('id','myBtn1');
    console.log(btn1.id);
    btn1.setAttribute('data-index','40');
    console.log(btn1.getAttribute('data-index'));
    //建议:除了设置自定义特性以外,都建议通过设置属性来设置特性,方便明了.

removeAttribute():用于彻底删除元素的特性,调用这个方 法不仅会清除特性的值,而且也会从元素中完全删除特性,这个方法并不常用,但在序列化 DOM 元素时,可以通过它来确切地指定要包含哪些特性。

  • 3.4属性attributes

attributes属性:Element类型是使用attributes属性的唯一一个DOM节点类型,attributes属性中包含一个NamedNodeMap,与NodeList类似,也是一个“动态”的集合,元素的每一个特性都由一个Attr节点表示,每个节点都保存在NamedNodeMap对象中.

    var btn1 = document.getElementById('btn1'),attrs = btn1.attributes;
    console.log(attrs);
    for(var i=0,len=attrs.length;i<len;i++){
        console.log(attrs[i].nodeType);
        console.log(attrs[i].nodeValue);
    }

attributes作为NamedNodeMap,有以下方法:①getNamedItem:返回特定nodeName的节点,②removeNamedItem:移除特定nodeName的节点,③setNamedItem(node):向列表中添加节点,④item(pos):返回位于数字pos位置的节点.

    console.log(attrs.getNamedItem('class'));
    console.log(attrs.getNamedItem('data-index'));
    console.log(attrs.item(3));
    //方括号访问:
    console.log(attrs["id"]);
    //赋值
    attrs["id"].nodeValue = 'myBtn';

一般取特性,给特性赋值都很少使用attributes,直接使用getAttribute(),setAttribute()更方便,一般用于遍历特性:

    function outputAttributes(element) {
        var pairs = [],
                attrName,
                attrValue,
                i,
                len;
        for (i = 0, len = element.attributes.length; i < len; i++) {
            attrName = element.attributes[i].nodeName;
            attrValue = element.attributes[i].nodeValue;
            if (element.attributes[i].specified) {
                pairs.push(attrName + "=\"" + attrValue + "\"");
            }
        }
        return pairs.join(" ");
    }
  说明:每个特性节点都有一个名为specified的属性,这个属性的值如果      为 true,
  则意味着要么是在HTML中指定了相应特性,
  要么是通过setAttribute()方法设置了该特性.
  这里针对的是IE7及更早版本的问题:IE7及更早的版本会返回HTML元    素中所有可能的特性,
  包括没有指定的特性.
  • 3.5创建元素
    //创建元素
    var div = document.createElement("div");
    console.log(div.ownerDocument == document);
    //在IE中可以以另一种方式使用createElement(),即为这个方法传入完整的元素标签,也可以包含属性:
    var div1 = document.createElement("<div id=\"myNewDiv\" class=\"box\"></div >");
    //这种方式有助于避开在 IE7 及更早版本中动态创建元素的某些问题(在此不做列举),其他浏览器都不支持这种用法
  • 3.6元素的子节点

元素的子节点:子节点有可能是元素、文本节点、注释或处理指令.不同浏览器对于看待子节点有不同:

html:
<ul class="ul-list">
    <li>第一行</li>
    <li>第二行</li>
    <li>第三行</li>
</ul>
js:
var ulList = document.getElementsByClassName('ul-list')[0];
console.log(ulList.childNodes);

如果是 IE 来解析这些代码,ul有3个子节点,其他浏览器解析的话有7个,包括了4个text节点.如果将元素间的空白符删除,将返回相同数量的子节点.
元素也支持 getElementsByTagName() 方法,探索的起点是当前元素.

4.Text类型

nodeType是3,nodeName是 #text ,nodeValue/data是节点所包含的文本:

    var text = document.getElementsByClassName('text-con')[0].firstChild;
    console.log(text.nodeType);
    console.log(text.nodeName);
    console.log(text.nodeValue);

操作方法:除了以下的,还有splitText(),substringData():

    text.nodeValue = "修改的文本";
    console.log(text.nodeValue);
    text.appendData('我是新增加进来的文本');
    text.insertData(3,'插入的文本');
    text.deleteData(0,3);
    text.replaceData(0,3,'我是替代进来的文本');
    console.log(text.length);
  • 4.1创建文本节点
    var element = document.createElement("div");
    element.className = "message";
    var textNode = document.createTextNode("我是文本");
    element.appendChild(textNode);
    var anotherTextNode = document.createTextNode("我是另外的文本");
    element.appendChild(anotherTextNode);
    document.body.appendChild(element);
    //这种情况下两个节点中的文本就会连起来显示,中间不会有空格,因为两个文本节点是同胞节点.
  • 4.2规范化文本节点

规范化就是把相邻的文本节点合并成一个文本节点:

    接上:
    console.log(element.childNodes);//打印2个文本节点
    element.normalize();//规范化
    console.log(element.childNodes);//打印1个文本节点
  • 4.3分割文本节点

在指定位置把一个文本节点分割开2个文本节点:

    element.firstChild.splitText(5);
    //第一个是"我是文本我"(从0开始,5之前结束),第二个是"是另外的文本"
    console.log(element.childNodes);

5.Comment类型

Comment即注释:nodeType为8,nodeName为#comment,nodeValue/data是注释的内容.Comment 类型与 Text 类型继承自相同的基类,因此它拥有除 splitText()之外的所有字符串操作方法:

    var div = document.getElementsByClassName('div-con')[0];
    div.append(document.createComment('我是DOM添加的注释内容啊'));

6.CDATASection类型

CDATASection 类型只针对基于 XML 的文档,表示的是 CDATA 区域。与 Comment 类似, CDATASection 类型继承自 Text 类型,因此拥有除 splitText()之外的所有字符串操作方法。

  • nodeType为4
  • nodeName为#cdata-section
  • nodeValue是是 CDATA 区域中的内容

7.DocumentType类型

DocumentType 类型在 Web 浏览器中并不常用,仅有 Firefox、Safari 和 Opera 和部分chrome支持它.

  • nodeType为0
  • nodeName的值为 doctype 的名称
  • nodeValue 的值为 null
  • parentNode 是 Document

在 DOM1 级中,DocumentType 对象不能动态创建,而只能通过解析文档代码的方式来创建。支持它的浏览器会把 DocumentType 对象保存在 document.doctype 中。
DOM1 级描述了 DocumentType 对象的 3 个属性:name、entities 和 notations。其中,name 表示文档类型的名称; entities 是由文档类型描述的实体的 NamedNodeMap 对象;notations 是由文档类型描述的符号的 NamedNodeMap 对象。通常,浏览器中的文档使用的都是 HTML 或 XHTML 文档类型,因而 entities 和 notations 都是空列表(列表中的项来自行内文档类型声明).
所以,只有 name 属性是有用的。这个属性中保存的是文档类型的名称,也就是出现在<!DOCTYPE 之后的文本。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
  "http://www.w3.org/TR/html4/strict.dtd">
//DocumentType 的 name 属性中保存的就是html

IE 及更早版本不支持 DocumentType,因此 document.doctype 的值始终都等于 null。可是, 这些浏览器会把文档类型声明错误地解释为注释,并且为它创建一个注释节点。IE9 会给 document.doctype 赋正确的对象,但仍然不支持访问 DocumentType 类型。

8.DocumentFragment类型

在所有节点类型中,只有 DocumentFragment 在文档中没有对应的标记。DOM 规定文档片段是一种“轻量级”的文档,可以包含和控制节点,但不会像完整的文档那样占用额外的资源。

  • nodeType为11
  • nodeName 的值为"#document-fragment"
  • nodeValue为null
  • parentNode为null
  • 子节点可以是Element、ProcessingInstruction、Comment、Text、CDATASection 或EntityReference.
    文档片段继承了 Node 的所有方法,通常用于执行那些针对文档的 DOM 操作。常用document fragment当做仓库使用,避免多次渲染和布局文档:
    var fragment = document.createDocumentFragment(),ul = document.getElementById('temp-ul');
    var li = null;
    for(var i=0;i<3;i++){
        li = document.createElement('li');
        li.append(document.createTextNode('我是新创建的第'+i+'个li'));
        fragment.append(li);
    }
    ul.append(fragment);

9.Attr类型

特性节点就是存在于元素的 attributes 属性中的节点:

  • nodeType是2
  • nodeName 的值是特性的名称
  • nodeValue 的值是特性的值
  • parentNode 的值为 null
  • 在 HTML 中不支持(没有)子节点,在 XML 中子节点可以是 Text 或 EntityReference

尽管它们也是节点,但特性却不被认为是 DOM 文档树的一部分。我们最常使用的是 getAttribute()、setAttribute()和 remveAttribute()方法,很少直接引用特性节点。
Attr 对象有 3 个属性:name、value 和 specified。其中,name 是特性名称(与nodeName的值相同),value 是特性的值(与nodeValue的值相同),而 specified是一个布尔值,用以区别特性是在代码中指定的,还是默认的。
创建Attr和赋给元素使用:document.createAttribute和ele.setAttributeNode.

相关文章

  • dom总结:节点层次

    HTML可以描绘成一个多层节点构成的结构,文档节点是每个文档的根节点, 元素被称之为文档元素,是文档的最外层元素。...

  • 什么是dom树

    介绍DOM,以及对DOM分类和功能的说明。 DOM 节点:介绍DOM节点分类和节点层次。 介绍HTML DOM节点...

  • 15、DOM初识1

    DOM: Document Object Model (文档对象模型) DOM节点: 节点和节点层次的概念?节点:...

  • 【DOM】节点层次

    DOM(文档对象模型)是针对HTML和XML文档的一个API(应用程序编程接口)。DOM描绘了一个层次化的节点树,...

  • DOM

    DOM(文档对象模型)是针对HTML和XML文档的API,描绘了一个层次化的节点树 节点层次DOM可以将任何HTM...

  • DOM对象控制HTML元素

    以下内容,摘自慕课网 将HTML代码分解为DOM节点层次图: 节点属性 在文档对象模型(DOM)中,每个节点都是一...

  • Javascript中的Dom概念和Node类型(一)

    一、Dom的概念和节点层次 Dom:Document Object Model 文档对象模型,可以将任何 html...

  • 【javascript】DOM—节点层次—Node类型

    节点层次 DOM 可以将任何HTML 或XML 文档描绘成一个由多层节点构成的结构。 节点之间的关系构成了层次,而...

  • React的插槽solt

    插槽(Portals)能将子节点渲染到父组件的 DOM 层次之外

  • JS之DOM

    一、节点层次 DOM是针对 HTML 和 XML 文档的一个API(应用程序编程接口)。DOM描绘了一个层次化的节...

网友评论

    本文标题:dom总结:节点层次

    本文链接:https://www.haomeiwen.com/subject/nrfxaxtx.html