zoukankan      html  css  js  c++  java
  • 18.DOM进阶

    DOM进阶

    学习要点:
    1.DOM类型
    2.DOM扩展
    3.DOM操作内容

    DOM自身存在很多类型,在DOM基础课程中大部分都有所接触,比如Element类型,表示的是元素节点,再比如
    Text类型:表示的是文本节点。DOM也提供了一些扩展功能。

    一、DOM类型
    DOM基础课程中,我们了解了DOM的节点并且了解怎么查询和操作节点,而本身这些不同的节点,又有着不同的
    类型。

    DOM 类型
    类型名 说明
    Node 表示所有类型值的统一接口,IE不支持
    Document 表示文档类型
    Element 表示元素节点类型
    Text 表示文本节点
    Comment 表示文档中的注释类型
    CDATASection 表示CDATA区域类型
    DocumentType 表示文档声明
    DocumentFragment 表示文档片段类型
    Attr 表示属性节点类型

    1.Node类型
    Node接口是DOM1级就定义了,Node接口定义了12个数值常量以表示每个节点的类型值,除了IE之外,所有
    浏览器都可以访问这个类型。

    Node的常量
    常量名 说明 nodeType值
    ELEMENT_NODE 元素 1
    ATTRIBUTE_NODE 属性 2
    TEXT_NODE 文本 3
    CDATA_SECTION_NODE CDATA 4
    ENTITY_REFERENCE_NODE 实体参考 5
    ENTITY_NODE 实体 6
    PROCESSING_INSIRUCETION_NODE 处理指令 7
    COMMENT_NODE 注释 8
    DOCUMENT_NODE 文档根 9
    DOCUMENT_TYPE_NODE doctype 10
    DOCUMENT_FRAGMENT_NODE 文档片段 11
    NOTATION_NODE 符号 12

    虽然这里介绍了12种节点对象的属性,用的多的其实也就几个而已。
    alert(Node.ELEMENT_NODE); //1.元素节点类型值
    alert(Node.TEXT_NODE); //2.文本节点类型值

    我们建议使用Node类型的属性来代替1,2这些阿拉伯数字,有可能大家会觉得这样岂不是很繁琐吗?并且还有一个
    问题就是IE不支持Node类型。

    如果只有两个属性的话,用1,2来代替会特别方便,但如果属性特别多的情况下,1,2,3,4,5,6,7,8,9,10,11,12,
    你根本就分不清那个数字代表的是哪个节点,当然,如果你只用1,2两个节点,那就另当别论了。

    IE不支持,我们可以模拟一个类,让IE也支持。
    if(typeof Node == 'undefined'){ //IE返回
    window.Node ={
    ELEMENT_NODE : 1,
    TEXT_NODE : 3
    };
    }

    2.Document类型
    Document类型表示文档,或文档的根节点,而这个节点时隐藏的,没有具体的元素标签。
    document; //document
    document.nodeType; //9,类型值
    document.childNodes[0]; //DocumentType,第一个子节点对象,IE理解为注释
    document.childNodes[0].nodeType; //非IE为10,IE为8
    document.childNodes[0].nodeName; //火狐为HTML,谷歌为html,IE为#comment
    document.childNodes[1]; //HTML.HtmlElement
    document.childNodes[1].nodeType; //HTML

    如果想直接得到<html>标签的元素节点对象HTML.HtmlElement,不必使用childNodes属性这么麻烦,可以使
    用documentElement即可。

    document.documentElement; //HTML.HtmlElement

    在很多情况下,我们并不需要得到<html>标签的元素节点,而需要得到更常用的<body>标签,之前我们采用的
    是:document.getElementsByTagName('body')[0],,那么这里提供了一个更简便的方法:document.body

    document.body; //HTML.BodyElement

    在<html>之前还有一个文档声明;<!DOCTYPE>会作为某些浏览器的第一个节点来处理,这里提供一个简便
    方法来处理:document.dctype。
    document.doctype; //DocumentType

    PS:IE8中,如果使用子节点访问,IE8之前会解释为让注释类型Comment节点,而document.doctyoe则会返回
    null。
    document.childNodes[0].nodeName //IE会是#Comment

    在Document中有一些遗留的属性和对象合集,可以使用的帮助我们精确的处理一些任务。


    //属性
    document.title; //获取和设置<title>标签的值
    document.URL; //获取URL路径
    document.domain; //获取域名,服务器端
    document.referrer; //获取上一个URL,服务器端


    //对象合集
    document.anchors; //获取文档中带name属性的<a>元素集合
    document.links; //获取文档中带href属性的<a>元素集合
    document.applets; //获取文档中<applet>元素集合,已不用
    document.forms; //获取文档中<form>元素集合
    document.images; //获取文档中<img>元素集合

    3.Element类型
    Element类型用于表现HTML中的元素节点,在DOM基础那章,我们已经可以对元素节点进行查找、创建等操作
    元素节点的nodeType为1,nodeName为元素的标签名。
    元素节点对象在IE浏览器可以返回它具体元素节点的对象类型。

    元素对应类型表

    元素名 类型
    HTML HTML.HtmlElement
    DIV HTML.DivElement
    BODY HTML.BodyElement
    p HTML.ParamElement

    PS:以上给出了部分对应,更多的元素对应类型,直接访问调用即可。

    4.Text类型
    Text类型用于表现文本节点类型,文本不包含HTML,或包含转义后的HTML。文本节点的nodeType为3。
    在同时创建两个同一级别的文本节点的时候,会产生分离的两个节点。
    var box = document.createElement('div');
    var text = document.createTextNode('Mr');
    var text2 = document.createTextNode('Lee');
    box.appendChild(text);
    box.appendChild(text2);
    document.body.appendChild(box);
    alert(box.childNodes.length); //2,两个文本节点


    PS:把两个文本节点合并在一起使用normalize()即可
    box.normalize(); //合并成一个节点

    PS:有合并就有分离,通过splitText(num)即可实现节点分离。
    box.firstChild.splitText(3); //分离一个节点,把前三个分离成新节点

    除了上面的两种方法外,Text还提供了一些别的DOM操作的方法如下:
    var box = document.getElementById('box');

    box.firstChild.deleteData(0,2); //删除从0位置的2个字符
    box.firstChild.insertData(0,'Hello'); //从0位置添加指定字符
    box.firstChild.replaceData(0,2,'Miss'); //从0位置替换掉2个指定字符
    box.firstChild.substringData(0,2); //从0位置获取2个字符,直接输出
    alert(box.firstChild.nodeValue); //输出结果

    5.Comment类型
    Comment类型表示文档中的注释,nodeType是8,nodeName是#Comment,nodeValue是注释的内容。

    var box = document.getElementById('box');
    alert(box.firstChild); //Comment

    PS:在IE中,注释节点可以使用!号当作元素来访问。
    var comment = document.getElementsByTagName('!');
    alert(comment.length);


    6.Attr类型
    Attr类型表示文元素中的属性。nodeType为2,nodeName为属性名,nodeValue为属性值,DOM基础已经
    详细介绍。


    二、DOM扩展
    1.呈现模式
    从IE6开始区分标准模式和混杂模式(怪异模式),主要是看文档的声明。IE为document对象添加一个名为
    compatMode属性。这个属性可以识别IE浏览器的文档处于什么模式,如果是标准模式,则返回CSS1Compat
    ,如果时混杂模式则返回BackCompat。
    if(document.compatMode == 'CSS1Compat'){
    alert(document.documentElement.clientWidth);
    }else{
    alert(document.body.clientWidth);
    }

    PS:后来Firefox、Opera和Chome都实现了这个属性。从IE8后,又引入了documentMode新属性,因为IE8
    有3种呈现模式分别为标准模式8,仿真模式7,混杂模式5。所以如果想测试IE8的标准模式,就判断
    document.documentMode > 7即可。

    2.滚动
    DOM提供了一些滚动页面的方法,如下:
    document.getElementById('box').scrollIntoView(); //设置指定可见,将指定的节点滚动到可见范围


    3.children属性
    由于子节点空白问题,IE和其他浏览器解释不一致。虽然可以过滤掉,但如果只是想得到有效子节点,可以使用
    children属性,支持的浏览器为:IE5+、Firefox3.5+、Safari2+、Opera8+和Chrome,这个属性是非标准的。
    var box = document.getElementById('box');
    alert(box.children.length); //得到有效子节点数目,忽略掉了空白节点

    4.contains()方法
    判断一个节点是不是另一个节点的后代,我们可以使用contains()方法,这个方法是IE率先使用的,开发人员无须
    遍历即可获取此信息。
    var box = document.getElementById('box');
    alert(box.contains(box.firstChild)); //true

    PS:早期的Firefox不支持这个方法,新版的支持了,其他浏览器也都支持,Safari浏览器支持的有问题,无法使
    用,所以,必须做兼容。

    function contains(refNode , otherNode){
    if(typeof refNode.contains != 'undefined'){
    return refNode.contains(otherNode);
    }else if(typeof refNode.compareDocumentPosition == 'function'){
    return refNode.compareDocumentPosition(otherNode) > 16;
    }
    }

    在Firefox的DOM3级实现中提供了一个替代的方法compareDocumentPosition()方法。
    这个方法确定两个节点之间的关系。

    var box = document.getElementById('box');
    alert(box.compareDocumentPosition(box.firstChild)); //20,大于16就是包含关系

    关系掩码表
    掩码 节点关系
    1 无关(节点不存在)
    2 居前(节点在参考点之前)
    4 居后(节点在参考点之后)
    8 包含(节点是参考点的祖先)
    16 被包含(节点时参考点的后代)

    PS:为什么会出现20,那是因为满足了4和16两项,最后相加了。为了能让所有浏览器都可以兼容,我们必须
    写一个兼容性的函数。

    //传递参考节点(父节点),和其他节点(子节点)
    function contains(refNode , otherNode){
    //判断支持comtains,并且非Safari浏览器
    if(typeof refNode.contains != 'undefined' && !(BrowserDetect.browser == 'Safari' && BrowserDetect.version < 3)){
    return refNode.comment(otherNode);
    //判断支持compareDocumentPosition的浏览器,大于16就是包含
    }else if(typeof refNode.compareDocumentPosition == 'function'){
    return !!(refNode.compareDocumentPosition(otherNode) > 16);
    }else{
    //更低的浏览器兼容,通过递归一个个获取他的父节点是否存在
    var node = otherNode.parentNode;
    do{
    if(node == refNode){
    return true;
    }else{
    node = node.parentNode;
    }
    }while (node != null);
    }
    return false;
    }


    三、DOM操作内容
    虽然在之前我们已经学习了各种DOM操作的方法,这里所介绍是innerText、innerHTML、otherText和otherHTML
    等属性。除了之前用过的innerHTML之外。其他三个还没有涉及到。

    1.innerText属性
    document.getElementById('box').innerText; //获取文本内容(如有html直接过滤掉)
    document.getElementById('box').innerText='Mr.Lee';//设置文本(如有html转义)


    PS:除了Firefix之外,其他浏览器均支持这个方法。但Firefox的DOM3级提供了另外一个类似的属性:
    textCotent,做上兼容可通用。

    document.getElementById('box').textContent; //Firefox支持

    //兼容方案
    function getInnerText(element){
    return(typeof element.textContent == 'string')?element.textContent : element.innerText;
    }
    function setInnerText(element.text){
    if(typeof.element.textContent == 'string'){
    element.textContent = text;
    }else{
    element.innerText = text;
    }
    }

    2.innerHTML属性
    这个属性之前就已经研究过,不拒绝HTML。
    document.getElementById('box').innerTHML; //获取文本(不过滤HTML)
    document.getElementById('box').innerHTML = '<b>123</b>'; //可解析HTML

    虽然innerHTML可插入HTML,但本身还是有一定的限制,也就是所谓的作用域元素,离开这个作用域就无效了。
    box.innerHTML = "<script>alert('Lee')</script>"; //<script>元素不能执行
    box.innerHTML = "<style>background:red;</style>"; //<style>元素不能被执行

    3.outerText
    outerText在取值的时候和innerHTML一样,同时火狐不支持,而赋值方法相当危险,它不单替换了文本内容,
    还将元素直接抹去。

    var box = document.getElementById('box');
    box.outerText = '<b>123</b>';
    alert(document.getElementById('box')); //null,建议不去使用


    4.outerHTML
    outerHTML属性在取值和innerHTML一致,但和outerText也一样,很危险,赋值的之后将元素抹去。
    var box = document.getElementById('box');
    box.outerHTML = '123';
    alert(document.getElementById('box')); //null,建议不去使用

    PS:关于最常用的innerHTML属性和节点操作方法的比较,在插入大量HTML标记时使用innerHTML的效率明显
    要高很多,因为在设置innerHTML时,会创建一个HTML解析器,这个解析器是浏览器级别的(c++编写的),
    因此执行Javascript会快的多。但创建和销毁HTML解析器也会带来性能损失。最好控制在最合理的范围内,如下:
    for(var i = o ; i<10 ; i++){
    ul.innerHTML = '<li>inem<li>'; //避免频繁
    }
    //改
    for(var i = 0 ; i<10; i++){
    a = '<li>item<li>'; //临时保存
    }
    ul.innerHTML = a;


    HTML5中新API:
    按类名查找元素:IE8不支持
    var elems=
    document/parentNode.getElementsByClassName("类名")

    按选择器查找元素:IE8支持!
    按照选择器查找符合条件的元素:
    var firstElem=document.querySelector("CSS选择器");
    var elems=document.querySelectorAll("CSS选择器");
    原生API:底层实现!

    vs 旧getxxxByXXX方法
    旧getxxxByXXX方法:返回仅是实际元素对象的引用。还须返回树结构中遍历对象的属性。
    selectors API:返回结果包含完整的元素对象和属性。不需要再返回树中遍历,即可访问元素的所有属性!

    DEMO:二级菜单弹出
    onmouseover: 鼠标进入元素边界时,*发生一次*!
    onmouseout: 鼠标移出元素边界时,触发一次

    DOM树的快速获得指定节点:
    document.documentElement: 整个<html>的内容——了解
    document.body:直接获得body元素!——重要

    *爬树:
    向上爬:parentNode:
    向下爬:querySelectorAll:*

    元素树:节点树去掉属性节点和文本节点后得到的只有元素组成的树。
    节点树 vs 元素树:
    父节点 parentNode parentElementNode
    所有子节点 childNodes children
    第一个子节点 firstChild firstElementChild
    最后子节点 lastChild lastElementChild
    前一个兄弟 previousSibling previousElementSibling
    后一个兄弟 nextSibling nextElementSibling


    动态创建节点:3步:
    1. 创建空节点:
    var newElem=document.createElement("标签名");
    比如:var a=document.createElement("a");
    <a></a>
    2. 设置节点对象必要属性:
    比如:a.href="http://tmooc.cn";
    a.innerHTML="tmooc";
    <a href="http://tmooc.cn">tmooc</a>
    ************************
    *3. 将节点挂到指定父元素下*
    //向父元素末尾追加新元素
    parentNode.appendChild(newElem);
    //在父元素中间,插入新元素
    parentNode.insertBefore(newElem,后一个现有元素对象)

  • 相关阅读:
    Oracle中有大量的sniped会话
    Error 1130: Host '127.0.0.1' is not allowed to connect to this MySQL server
    汉字转换为拼音以及缩写(javascript)
    高效率随机删除数据(不重复)
    vs2010 舒服背景 优雅字体 配置
    mvc中的ViewData用到webfrom中去
    jquery ajax return值 没有返回 的解决方法
    zShowBox (图片放大展示jquery版 兼容性好)
    动感效果的TAB选项卡 jquery 插件
    loading 加载提示······
  • 原文地址:https://www.cnblogs.com/journey-IT/p/5260270.html
Copyright © 2011-2022 走看看