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,后一个现有元素对象)

  • 相关阅读:
    Dedecms(织梦)文章内容页和图片集内容页,调用缩略图的方法
    如何修改织梦dedecms文章标题的最大长度
    织梦自定义表单后台管理增加全选功能,批量删除垃圾留言信息
    自定义表单SQL命令行批量删除垃圾留言
    织梦后台卡死的原因分析及开关功能解决办法
    织梦网站迁移的几种方法
    Dedecms(织梦)文章内容页和图片集内容页,调用缩略图的方法
    织梦CMS被挂马特征汇总
    DedeCMS模板中用彩色tag做彩色关键词
    HDU6038
  • 原文地址:https://www.cnblogs.com/journey-IT/p/5260270.html
Copyright © 2011-2022 走看看