DOM

作者: EdmundChen | 来源:发表于2018-05-03 22:59 被阅读78次

    DOM

    IE中的所有DOM对象都是以COM对象的形式实现的。

    节点层次

    DOM可以将任何HTML或XML文档描绘成一个由多层节点构成的结构。节点分为几种不同的类型:

    文档元素: 在HTML页面中,文档元素始终都是<html>元素,(在XML中何元素都可能成为文档元素)

    12种DOM节点层次(继承自一个基类型)

    • 1、node类型
    • 2、Document类型
    • 3、Element类型
    • 4、Text类型
    • 5、Comment类型
    • 6、CDATASection类型(only XML文档)
    • 7、DocumentType(类型)(在Web浏览器中并不常用)
    • 8、DocumentFragment
    • 9、Attr类型
    • ... 其他

    一、Node类型(12个数值常量来表明节点的类型。)

    DOM1级定义了一个Node接口,该接口将由DOM中的所有节点类型实现。
    JavaScript中的所有节点类型都继承自Node类型,因此所有节点类型都共享着相同的基本属性和方法。

    1、dom.nodeNamenodeValue

    这两个属性的值完全取决于节点的类型,对于元素节点,node-Name中保存的始终都是元素的标签名,而nodeValue的值则始终为null。

    2、节点的关系 childNodesparentNodehasChildNodes()

    每个节点都有一个childNodes属性,其中保存着一个NodeList对象,是一种类数组对象,用于保存一组有序的节点。childNodes列表中的每个节点相互之间都是同胞节点。通过使用列表中每个节点的previousSiblingnextSibling属性,可以访问同一列表中的其他节点。父节点与其第一个和最后一个子节点之间也存在特殊关系。父节点的firstChildlastChild属性分别指向其childNodes列表中第一个和最后一个节点。

     ParentNode.lastElementChild
     ParentNode.firstElementChild
    
    3、操作节点
    • appendChild(): 将一个节点添加到指定父节点的子节点列表末尾, 如果传入到appendChild()中的节点已经是文档的一部分了,那结果就是将该节点从原来的位置转移到新位置。即使可以将DOM树看成是由一系列指针连接起来的,但任何DOM节点也不能同时出现在文档中的多个位置上。
    //将一个节点添加到指定父节点的子节点列表末尾。
    const child = node.appendChild(child);
    // node: 是要插入子节点的父节点.
    // child: 即是参数又是这个方法的返回值.
    
    • insertBefore() 参考节点之前插入一个节点作为一个指定父节点的子节点
    const insertedElement = parentElement.insertBefore(newElement, referenceElement);
    //1. referenceElement为null则newElement将被插入到子节点的末尾。
    //2. 如果newElement已经在DOM树中,newElement首先会从DOM树中移除。
    

    insertedElement 是被插入的节点,即 newElement
    parentElement 是新插入节点的父节点
    newElement 是被插入的节点
    referenceElement 在插入newElement之前的那个节点

    • replaceChild(): 接受的两个参数是:要插入的节点和要替换的节点
    replacedNode = parentNode.replaceChild(newChild, oldChild);
    // newChild 用来替换 oldChild 的新节点。如果该节点已经存在于DOM树中,则它会被从原始位置删除。
    // oldChild  被替换掉的原始节点。
    // replacedNode 和 oldChild相等。
    
    • removeChild() 从DOM中删除一个子节点。返回删除的节点
    let oldChild = node.removeChild(child);
    //OR
    element.removeChild(child);
    // child 是要移除的那个子节点.
    // node 是child的父节点.
    // oldChild保存对删除的子节点的引用. oldChild === child.
    
    • cloneNode(): 接受一个布尔值参数,表示是否执行深复制。在参数为true的情况下,执行深复制,也就是复制节点及其整个子节点树;在参数为false的情况下,执行浅复制,即只复制节点本身。
    • normalize()

    cloneNode 和 normalize 所有类型的节点都有

    二、Document 类型(document对象-文档对象)

    JavaScript通过Document类型表示文档。在浏览器中,document对象继承自Document类型的一个实例,表示整个HTML页面,是window对象的一个属性

    • nodeType的值为9;
    • nodeName的值为"#document";
    • nodeValue的值为null;
    • parentNode的值为null;
    • ownerDocument的值为null;

    最常见的应用还是作为HTMLDocument实例的document对象

    1、文档的子节点

    DOM标准规定Document节点的子节点可以是DoumentTypeElementProcessingInstructionComment,但还有两个内置的访问其子节点的快捷方式。

    • documentElement属性,该属性始终指向<html>元素。
    • childNodes列表访问文档元素,但通过documentElement属性则能更快捷、更直接地访问该元素。
    // 取得对<html>的引用
    var html = document.documentElement;
    // true
    alert(html === document.childNodes[0]);
    //true
    alert(html === document.firstChild);
    //取得对<body>的引用
    var body = document.body;
    //取得对<!DOCTYPE>的引用
    var doctype = document.doctype;
    
    2、文档信息

    作为HTMLDocument的一个实例,document对象还有一些标准的Document对象所没有的属性。

    //取得文档标题
    var originalTitle = document.title;
    //设置文档标题
    document.title = "New page title";
    //取得完整的URL
    var url = document.URL;
    //取得域名
    var domain = document.domain;
    //取得来源页面的URL
    var referrer = document.referrer;
    

    只有domain是可以设置的。但由于安全方面的限制,也并非可以给domain设置任何值。如果URL中包含一个子域名,例如p2p.wrox.com,那么就只能将domain设置为"wrox.com"(URL中包含"www",如www.wrox.com时,也是如此)。不能将这个属性设置为URL中不包含的域,如下面的例子所示。

    //假设页面来自p2p.wrox.com域
    // 成功
    document.domain = "wrox.com";
    // 出错!
    document.domain = "nczonline.net";
    

    当页面中包含来自其他子域的框架或内嵌框架时,能够设置document.domain就非常方便了。由于跨域安全限制,来自不同子域的页面无法通过JavaScript通信。而通过将每个页面的doc-ument.domain设置为相同的值,这些页面就可以互相访问对方包含的JavaScript对象了。

    查找元素
    • getElementById()
    • getElementsByTagName()
    • getElementsByName() 只有HTMLDocument类型才有的方法
    • getElementsByClassName() (H5)

    classList 属性
    HTML5新增了一种操作类名的方式,可以让操作更简单也更安全,那就是为所有元素添加classList属性。这个classList属性是新集合类型DOMTokenList的实例。与其他DOM集合类似,DOMTokenList有一个表示自己包含多少元素的length属性,而要取得每个元素可以使用item()方法,也可以使用方括号语法。此外,这个新类型还定义如下方法。

    • add(value):将给定的字符串值添加到列表中。如果值已经存在,就不添加了。
    • contains(value):表示列表中是否存在给定的值,如果存在则返回true,否则返回false。
    • remove(value):从列表中删除给定的字符串。
    • toggle(value):如果列表中已经存在给定的值,删除它;如果列表中没有给定的值,添加它。
    特殊集合
    • document.anchors,包含文档中所有带name特性的<a>元素;
    • document.forms,包含文档中所有的<form>元素,与doc-ument.getElementsByTagName("form")得到的结果相同;
    • document.images,包含文档中所有的<img>元素,与doc-ument.getElementsByTagName ("img")得到的结果相同;
    • document.links,包含文档中所有带href特性的<a>元素。
    文档写入

    write()writeln()open()close()

    三、Element 类型

    除Document类型之外,Element类型就要算是Web编程中最常用的类型了。Element类型用于表现XML或HTML元素,提供了对元素标签名、子节点及特性的访问。

    • nodeType的值为1;
    • nodeName的值为元素的标签名;
    • nodeValue的值为null;
    • parentNode可能是Document或Element;
    • 其子节点可能是Element、Text、Comment、Processin-gInstruction、CDATASection或EntityReference
    <div id="myDiv"></div>
    //可以像下面这样取得这个元素及其标签名: 
    var div = document.getElementById("myDiv");
    //"DIV"
    alert(div.tagName);
    //true
    alert(div.tagName == div.nodeName);
    // 在HTML中,标签名始终都以全部大写表示
    
    1、HTML元素

    所有HTML元素都是由HTMLElement或者其更具体的子类型来表示的。

    2、操作特性
    • getAttribute()
    • setAttribute()
    • removeAttribute()
    3、attributes属性

    attributes属性中包含一个NamedNodeMap,与NodeList类似,也是一个“动态”的集合。元素的每一个特性都由一个Attr节点表示,每个节点都保存在NamedNodeMap对象中。NamedNodeMap对象拥有下列方法。

    4、创建元素

    document.createElement()

    var div = document.createElement("div");
    div.id = "myNewDiv";
    div.className = "box";
    document.body.appendChild(div);
    
    5、元素的子节点

    元素可以有任意数目的子节点和后代节点,因为元素可以是其他元素的子节点。元素的childNodes属性中包含了它的所有子节点,这些子节点有可能是元素、文本节点、注释或处理指令。

    四、Text 类型

    文本节点由Text类型表示,包含的是可以照字面解释的纯文本内容。纯文本中可以包含转义后的HTML字符,但不能包含HTML代码。

    • nodeType的值为3;
    • nodeName的值为"#text";
    • nodeValue的值为节点所包含的文本;
    • parentNode是一个Element;
    • 不支持(没有)子节点。

    可以通过nodeValue属性或data属性访问Text节点中包含的文本,这两个属性中包含的值相同。对nodeValue的修改也会通过data反映出来,反之亦然。使用下列方法可以操作节点中的文本。

    • appendData(text):将text添加到节点的末尾。
    • deleteData(offset,count):从offset指定的位置开始删除count个字符。
    • insertData(offset, text):在offset指定的位置插入text。
    • replaceData(offset, count, text):用text替换从offset指定的位置开始到offset+count为止处的文本。
    • splitText(offset):从offset指定的位置将当前文本节点分成
    • substringData(offset, count):提取从offset指定的位置开始到offset+count为止处的字符串。
    • length属性,保存着节点中字符的数目。
    <!-- 没有内容,也就没有文本节点 -->
    <div></div>
    <!-- 有空格,因而有一个文本节点 -->
    <div> </div>
    <!-- 有内容,因而有一个文本节点 -->
    <div>Hello World!</div>
    

    通过 nodeValue 访问值

    1.创建文本节点
    • document.createTextNode()
    var textNode = document.createTextNode("<strong>Hello</strong> world!");
    
    var element = document.createElement("div");
    element.className = "message";
    var textNode = document.createTextNode("Hello world!");
    
    element.appendChild(textNode);
    var anotherTextNode = document.createTextNode("Yippee!"); element.appendChild(anotherTextNode);
    
    document.body.appendChild(element);
    
    2.规范化文本节点normalize()。
    3.分割文本节点splitText()。

    五、Comment类型

    <div id="myDiv"><!--A comment --></div>
    

    DOM操作技术

    动态脚本

    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = "client.js";
    document.body.appendChild(script);
    

    动态样式

    var link = document.createElement("link");
    link.rel = "stylesheet";
    link.type = "text/css";
    link.href = "style.css";
    var head = document.getElementsByTagName("head")[0];
    head.appendChild(link);
    

    使用NodeList

    NodeList每当文档结构发生变化时,NodeList都会得到更新。

    小结

    DOM由各种节点构成,简要总结如下。

    • 最基本的节点类型是Node,用于抽象地表示文档中一个独立的部分;所有其他类型都继承自Node。
    • Document类型表示整个文档,是一组分层节点的根节点。在JavaScript中,document对象是Document的一个实例。使用document对象,有很多种方式可以查询和取得节点。
    • Element节点表示文档中的所有HTML或XML元素,可以用来操作这些元素的内容和特性。
    • 另外还有一些节点类型,分别表示文本内容、注释、文档类型、CDATA区域和文档片段。

    DOM扩展

    • querySelector()
    • querySelectorAll()
    • matchesSelector() 这个方法接收一个参数,即CSS选择符,如果调用元素与该选择符匹配,返回true;否则,返回false。

    H5

    一、焦点管理

    • document.activeElement
    • document.hasFocus()

    二、HTMLDocument 的变化

    • readyState属性
    document.readyState === 'loading'
    document.readyState === 'complete'
    
    • 字符集属性
    //"UTF-16"
    alert(document.charset);
    document.charset = "UTF-8";
    
    • 自定义数据属性
      HTML5规定可以为元素添加非标准的属性,但要添加前缀data-,目的是为元素提供与渲染无关的信息,或者提供语义信息。这些属性可以任意添加、随便命名,只要以data-开头即可。
      dataset属性来访问自定义属性的值。dataset属性的值是DOMStringMap的一个实例,也就是一个名值对儿的映射。在这个映射中,每个data-name形式的属性都会有一个对应的属性
    //本例中使用的方法仅用于演示
    var div = document.getElementById("myDiv");
    //取得自定义属性的值
    var appId = div.dataset.appId;
    var myName = div.dataset.myname;//设置值
    

    三、插入标记

    • innerHTML属性
    • outerHTML属性
    • insertAdjacentHTML()方法

    四、内存与性能问题

    // bad
    for (var i=0, len=values.length; i < len; i++){    
    //要避免这种频繁操作!!   
    ul.innerHTML += "<li>" + values[i] + "</li>";
    }
    // good
    var itemsHtml = ""; 
    for (var i=0, len=values.length; i < len; i++){    
    itemsHtml += "<li>" + values[i] + "</li>"; 
    }
    
    ul.innerHTML = itemsHtml; 
    

    五、scrollIntoView()

    scrollIntoView()可以在所有HTML元素上调用,通过滚动浏览器窗口或某个容器元素,调用元素就可以出现在视口中。如果给这个方法传入true作为参数,或者不传入任何参数,那么窗口滚动之后会让调用元素的顶部与视口顶部尽可能平齐。如果传入false作为参数,调用元素会尽可能全部出现在视口中,(可能的话,调用元素的底部会与视口顶部平齐。)不过顶部不一定平齐,例如:

    //让元素可见
    document.forms[0].scrollIntoView();
    

    相关文章

      网友评论

      • 米诺zuo:每次看你写的,就发现 o 原来还能这样的感觉。

      本文标题:DOM

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