JavaScript文档操作

文档对象模型(document object model,DOM)是W3C制定的一套技术规范,用来描述JavaScript脚本与HTML文档进行交互的Web标准。DOM规定了一系列标准接口,允许开发人员通过标准方式访问文档结构、操作网页内容、控制样式和行为等。

1、节点

节点(node)是DOM最基本的单元,并派生出不同类型的节点,它们共同构成文档结构模型。在网页中所有对象和内容都被称为节点,如文档、元素、文本、属性、注释等。

1.1、节点的类型

根据DOM规范,整个文档是一个文档节点,每个标签是一个元素节点,包含的文本是文本节点,标签的属性是一个属性节点,注释属于注释节点等。DOM节点类型说明如下表所示:
在这里插入图片描述

使用nodeType属性可以判断一个节点的类型,取值说明如下表所示:
在这里插入图片描述

1.2、节点的名称和值

使用nodeName和nodeValue属性可以读取节点的名称和值,属性取值说明如下表所示:
在这里插入图片描述

【示例】不同类型的节点,nodeName和nodeValue属性取值是不同的。元素的nodeName属性返回值是标签名,而元素的nodeValue属性返回值为null。因此在读取属性值之前,应该先检测类型:

    var node = document.getElementsByTagName("body")[0];
    if (node.nodeType==1)
        var value = node.nodeName;
    console.log(value);

nodeName属性在处理标签时比较实用,而nodeValue属性在处理文本信息时比较实用。

1.3、访问节点

DOM为Node类型定义如下属性,以方便JavaScript访问节点:

  • ownerDocument:返回当前节点的根元素(document对象)。
  • parentNode:返回当前节点的父节点。所有的节点都仅有一个父节点。
  • childNodes:返回当前节点的所有子节点的节点列表。
  • firstChild:返回当前节点的第一个子节点。
  • lastChild:返回当前节点的最后一个子节点。
  • nextSibling:返回当前节点之后相邻的同级节点。
  • previousSibling:返回当前节点之前相邻的同级节点。

【示例】针对下面文档结构:

    <!doctype html>
    <html>
    <head>
    <meta charset="utf-8">
    </head>
    <body><span class="red">body</span>元素</body></html>

可以使用下面方法访问body元素:

    var b = document.documentElement.lastChild;
    var b = document.documentElement.firstChild.nextSibling.nextSibling;

通过下面方法可以访问span包含的文本:

    var text = document.documentElement.lastChild.firstChild.firstChild.nodeValue;

1.4、操作节点

操作节点的基本方法如下表所示:
在这里插入图片描述
提示:appendChild()、insertBefore()、removeChild()、replaceChild() 4种方法用于对子节点进行操作。使用这4种方法之前,可以使用parentNode属性先获取父节点。另外,并不是所有类型的节点都有子节点,如果在不支持子节点的节点上调用这些方法将会导致错误发生。

【示例】为列表框绑定一个click事件处理程序,通过深度克隆,新的列表框没有添加JavaScript事件,仅克隆HTML类样式和style属性:

    <h1>DOM</h1>
    <p>DOM<cite>Document Object Model</cite>首字母简写,中文翻译为<b>文档对象模型</b>,是<i>W3C</i>组织推荐
的处理可扩展标识语言的标准编程接口。</p>
    <ul>
        <li class="red">D表示文档,HTML文档结构。</li>
        <li title="列表项目2">O表示对象,文档结构的JavaScript脚本化映射。</li>
        <li style="color:red;">M表示模型,脚本与结构交互的方法和行为。</li>
    </ul>
    <script>
    var ul = document.getElementsByTagName("ul")[0]; //获取列表元素
    ul.onclick = function(){                         //绑定事件处理程序
     this.style.border= "solid blue 1px";
    }
    var ul1 = ul.cloneNode(true);                    //深度克隆
    document.body.appendChild(ul1);                  //添加到文档树中body元素下
    </script>

2、文档

文档节点代表整个文档,使用document可以访问文档节点,它是文档内其他节点的访问入口,提供了操作其他节点的方法。文档节点是唯一的,也是只读的,主要特征:nodeType等于9、nodeName等于"#document"、nodeValue等于null、parentNode等于null、ownerDocument等于null。

2.1、访问文档

在不同环境中,获取文档节点的方法也不同,具体说明如下:

  • 在文档内部节点,使用ownerDocument访问。
  • 在脚本中,使用document访问。
  • 在框架页,使用contentDocument访问。
  • 在异步通信中,使用XMLHttpRequest对象的responseXML访问。

2.2、访问子节点

文档子节点包括以下元素:

  • doctype文档类型,如<!doctype html>
  • html元素,如<html>
  • 处理指令,如<?xml-stylesheet type="text/xsl" href="xsl.xsl" ?>
  • 注释,如<!--注释-->

访问方法如下:

  • 使用document.documentElement可以访问html元素。
  • 使用document.doctype可以访问doctype。注意,部分浏览器不支持。
  • 使用document.childNodes可以遍历子节点。
  • 使用document.firstChild可以访问第一个子节点,一般为doctype。
  • 使用document.lastChild可以访问最后一个子节点,如html元素或者注释。

2.3、访问特殊元素

文档中存在很多特殊元素,使用下面的方法可以获取,如果获取不到,将返回null。

  • 使用document.body可以访问body元素。
  • 使用document.head可以访问head元素。
  • 使用document.defaultView可以访问默认视图,即所属的窗口对象window。
  • 使用document.scrollingElement可以访问文档内滚动的元素。
  • 使用document.activeElement可以访问文档内获取焦点的元素。
  • 使用document.fullscreenElement可以访问文档内正在全屏显示的元素。

2.4、访问元素集合

document包含一组集合对象,使用它们可以快速地访问文档内元素,简单说明如下:

  • document.anchors:返回所有设置name属性的<a>标签。
  • document.links:返回所有设置href属性的<a>标签。
  • document.forms:返回所有form对象。
  • document.images:返回所有image对象。
  • document.applets:返回所有applet对象。
  • document.embeds:返回所有embed对象。
  • document.plugins:返回所有plugin对象。
  • document.scripts:返回所有script对象。
  • document.styleSheets:返回所有样式表集合。

2.5、访问文档信息

document包含很多信息,简单说明如下:

1.静态信息

  • document.URL:返回当前文档的网址。
  • document.domain:返回当前文档的域名,不包含协议和接口。
  • document.location:访问location对象。
  • document.lastModified:返回当前文档最后修改的时间。
  • document.title:返回当前文档的标题。
  • document.characterSet:返回当前文档的编码。
  • document.referrer:返回当前文档的访问者来自哪里。
  • document.dir:返回文字方向。
  • document.compatMode:返回浏览器处理文档的模式,值包括BackCompat(向后兼容模式)和CSS1Compat(严格模式)。

2.状态信息

  • document.hidden:表示当前页面是否可见。如果窗口最小化、切换页面,document.hidden返回true。
  • document.hidden:表示当前页面是否可见。如果窗口最小化、切换页面,document.hidden返回true。
  • document.readyState:返回当前文档的状态。取值包括loading(正在加载)、interactive(加载外部资源)、complete(加载完成)。

2.6、访问文档元素

document对象包含多个访问文档内元素的方法,简单说明如下:

  • getElementById():返回指定id属性值的元素。注意,id值要区分大小写,如果找到多个id相同的元素,则返回第一个元素,如果没有找到指定id值的元素,则返回null。
  • getElementsByTagName():返回所有指定标签名称的元素节点。
  • getElementsByName():返回所有指定名称(name属性值)的元素节点。该方法多用于表单结构中,用于获取单选按钮组或复选框组。
  • getElementsByName():返回所有指定名称(name属性值)的元素节点。该方法多用于表单结构中,用于获取单选按钮组或复选框组。

【示例】先获取所有图片,再通过namedItem(“news”);找到name为news的图片:

    <img src="1.gif" />
    <img src="2.gif" name="news" />
    <script>
    var images = document.getElementsByTagName("img");
    var news = images.namedItem("news");
    </script>

也可以使用下面用法获取页面中所有的元素,其中参数*表示所有元素:

    var allElements = document.getElementsByTagName("*");

3、元素

元素节点的主要特征:nodeType等于1、nodeName等于标签名称、nodeValue等于null。元素节点包含5个公共属性,即id(标识符)、title(提示标签)、lang(语言编码)、dir(语言方向)、className(CSS类样式),这些属性可读可写。

3.1、访问元素

1.getElementById()方法

使用getElementById()方法可以准确地获取文档中指定的元素,用法如下:

    document.getElementById(ID)

参数ID表示文档中对应元素的id属性值。如果文档中不存在指定元素,则返回值为null,该方法只适用于document对象。

【示例1】使用getElementById()方法获取<div id="box">对象,然后使用nodeName、nodeType、parentNode和childNodes属性查看该对象的节点类型、节点名称、父节点和第一个子节点的名称:

    <div id="box">盒子</div>
    <script>
    var box = document.getElementById("box");               //获取指定盒子的引用
    var info = "nodeName:" + box.nodeName;                 //获取该节点的名称
    info += "\rnodeType:" + box.nodeType;                  //获取该节点的类型
    info += "\rparentNode:" + box.parentNode.nodeName;     //获取该节点的父节点名称
    info += "\rchildNodes:" + box.childNodes[0].nodeName;  //获取该节点的子节点名称
    console.log(info);                                      //显示提示信息
    </script>

2.getElementByTagName()方法

使用getElementByTagName()方法可以获取指定标签名称的所有元素,用法如下:

    document.getElementsByTagName(tagName)

参数tagName表示指定名称的标签,该方法返回值为一个节点集合,使用length属性可以获取集合中包含元素的个数,利用下标可以访问其中某个元素对象。

【示例2】使用for循环获取每个p元素,并设置p元素的class属性为red:

    var p = document.getElementsByTagName("p");    //获取p元素的所有引用
    for(var i=0;i<p.length;i++){                   //遍历p数据集合
        p[i].setAttribute("class","red");          //为每个p元素定义red类样式
    }

3.2、遍历元素

使用parentNode、nextSibling、previousSibling、firstChild和lastChild属性可以遍历文档树中任意类型节点,包括空字符(文本节点)。HTML5新添加5个属性专门访问元素节点。

  • childElementCount:返回子元素的个数,不包括文本节点和注释。
  • firstElementChild:返回第一个子元素。
  • lastElementChild:返回最后一个子元素。
  • previousElementSibling:返回前一个相邻兄弟元素。
  • nextElementSibling:返回后一个相邻兄弟元素。

浏览器支持:IE 9+、Firefox 3.5+、Safari 4+、Chrome和Opera 10+。

3.3、创建元素

使用document对象的createElement()方法能够根据参数指定的标签名称创建一个新的元素,并返回新建元素的引用。用法如下:

    var element = document.createElement("tagName");

其中,element表示新建元素的引用,createElement()是document对象的一个方法,该方法只有一个参数,用来指定创建元素的标签名称。

【示例1】在当前文档中创建一个段落标记p,存储到变量p中。由于该变量表示一个元素节点,所以它的nodeType属性值等于1,而nodeName属性值等于p:

    var p = document.createElement("p");     //创建段落元素
    var info = "nodeName:" + p.nodeName;    //获取元素名称
    info += ",nodeType:" + p.nodeType;     //获取元素类型,如果为1则表示元素节点
    console.log(info);

使用createElement()方法创建的新元素不会被自动添加到文档里。如果要把这个元素添加到文档里,还需要使用appendChild()、insertBefore()或replaceChild()方法实现。

【示例2】演示把新创建的p元素增加到body元素下。当元素被添加到文档树中,就会立即显示出来:

    var p = document.createElement("p");      //创建段落元素
    document.body.appendChild(p);             //增加段落元素到body元素下

3.4、复制元素

cloneNode()方法可以创建一个节点的副本。

【示例】演示复制一个元素及其所有子节点。当复制其中创建的标题1节点之后,该节点所包含的子节点及文本节点都将复制过来,然后增加到body元素的尾部:

    var p = document.createElement("p");              //创建一个p元素
    var h1 = document.createElement("h1");            //创建一个h1元素
    var txt = document.createTextNode("Hello World"); //创建一个文本节点,文本内容为“Hello World”
    p.appendChild(txt);                               //把文本节点增加到段落中
    h1.appendChild(p);                                //把段落元素增加到标题元素中
    document.body.appendChild(h1);                    //把标题元素增加到body元素中
    var new_h1 = h1.cloneNode(true);                  //复制标题元素及其所有子节点
    document.body.appendChild(new_h1);                //把复制的新标题元素增加到文档中

注意:由于复制的节点会包含原节点的所有特性,如果原节点中包含id属性,就会出现id属性值重叠的情况。一般情况下,在同一个文档中,不同元素的id属性值应该不同。为了避免潜在冲突,应修改其中某个节点的id属性值。

3.5、插入元素

在文档中插入节点主要包括两种方法:

1.appendChild()方法

appendChild()方法可向当前节点的子节点列表的末尾添加新的子节点,用法如下:

    appendChild(newchild)

参数newchild表示新添加的节点对象,并返回新增的节点。

【示例】展示把段落文本增加到文档中指定的div元素中,使它成为当前节点的最后一个子节点:

    <div id="box"></div>
    <script>
    var p = document.createElement("p");            //创建段落节点
    var txt = document.createTextNode("盒模型");    //创建文本节点,文本内容为“盒模型”
    p.appendChild(txt);                             //把文本节点增加到段落节点中
    document.getElementById("box").appendChild(p);  //获取box元素,把段落节点增加进来
    </script>

如果文档树中已经存在参数节点,则将从文档树中删除,然后重新插入新的位置。如果添加节点是DocumentFragment节点,则不会直接插入,而是把它的子节点插入当前节点的末尾。

2.insertBefore()方法

使用insertBefore()方法可以在已有的子节点前插入一个新的子节点,用法如下:

    insertBefore(newchild,refchild)

其中,参数newchild表示新插入的节点,refchild表示插入新节点后的节点,用于指定插入节点的后面相邻的位置。插入成功后,该方法将返回新插入的子节点。

提示:insertBefore ()方法与appendChild()方法一样,可以把指定元素及其所包含的所有子节点都一起插入指定位置中。同时会先删除移动的元素,然后再重新插入新的位置。

3.6、删除元素

removeChild()方法可以从子节点列表中删除某个节点,用法如下:

    nodeObject.removeChild(node)

其中,参数node为要删除的节点。如果删除成功,则返回被删除节点;如果删除失败,则返回null。

当使用removeChild()方法删除节点时,该节点所包含的所有子节点将同时被删除。

【示例】单击按钮时将删除红盒子中的一级标题:

    <div id="red">
        <h1>红盒子</h1>
    </div>
    <div id="blue">蓝盒子</div>
    <button id="ok">移动</button>
    <script>
    var ok = document.getElementById("ok");             //获取按钮元素的引用
    ok.onclick = function(){                            //为按钮注册一个鼠标单击事件处理函数
     var red = document.getElementById("red");          //获取红色盒子的引用
     var h1 = document.getElementsByTagName("h1")[0];   //获取标题元素的引用
     red.removeChild(h1);                               //移出红盒子包含的标题元素
    }
    </script>

3.7、替换元素

replaceChild()方法可以将某个子节点替换为另一个子节点,用法如下:

    nodeObject.replaceChild(new_node,old_node)

其中,参数new_node为指定新的节点,old_node为被替换的节点。如果替换成功,则返回被替换的节点;如果替换失败,则返回null。

【示例】以上节示例为基础,重写脚本,新建一个二级标题元素,并替换红色盒子中的一级标题元素:

    var ok = document.getElementById("ok");             //获取按钮元素的引用
    ok.onclick = function(){                            //为按钮注册一个鼠标单击事件处理函数
     var red = document.getElementById("red");          //获取红色盒子的引用
     var h1 = document.getElementsByTagName("h1")[0];   //获取一级标题的引用
     var h2 = document.createElement("h2");             //创建二级标题元素,并引用
     red.replaceChild(h2,h1);                           //把一级标题替换为二级标题
    }

演示发现,当使用新创建的二级标题替换一级标题之后,则原来的一级标题所包含的标题文本已经不存在。这说明,替换节点的操作不是替换元素名称,而是替换其包含的所有子节点,以及其包含的所有内容。

4、文本

文本节点表示元素和属性的文本内容,包含纯文本内容、转义字符,但不包含HTML代码。文本节点不包含子节点。其主要特征:nodeType等于3、nodeName等于"#text"、nodeValue等于包含的文本。

4.1、创建文本

使用document对象的createTextNode()方法可以创建文本节点,用法如下:

    document.createTextNode(data)

参数data表示字符串。

【示例】创建一个新div元素,并为它设置class值为red,然后添加到文档中:

    var element = document.createElement("div");
    element.className = "red";
    document.body.appendChild(element);

注意:由于DOM操作等原因,可能会出现文本节点不包含文本,或者接连出现两个文本节点的情况。为了避免这种情况,一般应该在父元素上调用normalize()方法,删除空文本节点,合并相邻文本节点。

4.2、访问文本

使用nodeValue或data属性可以访问文本节点包含的文本。使用length属性可以获取包含文本的长度,利用该属性可以遍历文本节点中的每个字符。

4.3、读取HTML字符串

使用元素的innerHTML属性可以返回调用元素包含的所有子节点对应的HTML标记字符串。最初它是IE的私有属性,HTML5规范了innerHTML的使用,并得到所有浏览器的支持。

【示例】使用innerHTML属性读取div元素包含的HTML字符串:

    <div id="div1">
        <style type="text/css">p { color:red;}</style>
        <p><span>div</span>元素</p>
    </div>
    <script>
    var div = document.getElementById("div1");
    var s = div.innerHTML;
    console.log(s);
    </script>

4.4、插入HTML字符串

使用innerHTML属性可以根据传入的HTML字符串,创建新的DOM片段,然后用DOM片段完全替换调用元素原有的所有子节点。设置innerHTML属性值之后,可以像访问文档中的其他节点一样访问新创建的节点。

【示例】创建一个1000行的表格。先构造一个HTML字符串,然后更新DOM的innerHTML属性:

    <script>
    function tableInnerHTML() {
        var i, h = ['<table border="1" width="100%">'];
        h.push('<thead>');
        h.push('<tr><th>id<\/th><th>yes?<\/th><th>name<\/th><th>url<\/th><th>action<\/th><\/tr>');
        h.push('<\/thead>');
        h.push('<tbody>');
        for( i = 1; i <= 1000; i++) {
            h.push('<tr><td>');
            h.push(i);
            h.push('<\/td><td>');
            h.push('And the answer is... ' + (i % 2 ? 'yes' : 'no'));
            h.push('<\/td><td>');
            h.push('my name is #' + i);
            h.push('<\/td><td>');
            h.push('<a href="http://example.org/' + i + '.html">http://example.org/' + i + '.html<\/a>');
            h.push('<\/td><td>');
            h.push('<ul>');
            h.push(' <li><a href="edit.php?id=' + i + '">edit<\/a><\/li>');
            h.push(' <li><a href="delete.php?id="' + i + '-id001">delete<\/a><\/li>');
            h.push('<\/ul>');
            h.push('<\/td>');
            h.push('<\/tr>');
        }
        h.push('<\/tbody>');
        h.push('<\/table>');
        document.getElementById('here').innerHTML = h.join('');
    };
    </script>
    <div id="here"></div>
    <script>
    tableInnerHTML();
    </script>

如果通过DOM的document.createElement()和document.createTextNode()方法创建同样的表格,代码会非常冗长。在一个性能苛刻的操作中更新一大块HTML页面,innerHTML在大多数浏览器中执行得更快。

注意:使用innerHTML属性有一些限制。例如,在大多数浏览器中,通过innerHTML插入<script>标记后,并不会执行其中的脚本。

5、属性

属性节点的主要特征:nodeType等于2、nodeName等于属性的名称、nodeValue等于属性的值、parentNode等于null,在HTML中不包含子节点。属性节点继承于Node类型,包含3个专用属性:

  • name:表示属性名称,等效于nodeName。
  • value:表示属性值,可读可写,等效于nodeValue。
  • specified:如果属性值是在代码中设置的,则返回true;如果属性值为默认值,则返回false。

5.1、创建属性

使用document对象的createAttribute()方法可以创建属性节点,具体用法如下:

    document.createAttribute(name)

参数name表示新创建的属性的名称。

【示例1】创建一个属性节点,名称为align,值为center,然后为标签<div id="box">设置属性align,最后分别使用3种方法读取属性align的值:

    <div id="box">document.createAttribute(name)</div>
    <script>
    var element = document.getElementById("box");
    var attr = document.createAttribute("align");
    attr.value = "center";
    element.setAttributeNode(attr);
    console.log(element.attributes["align"].value);            //"center"
    console.log(element.getAttributeNode("align").value);      //"center"
    console.log(element.getAttribute("align"));                //"center"
    </script>

提示:属性节点一般位于元素的头部标签中。元素的属性列表会随着元素信息预先加载,并被存储在关联数组中。例如,针对下面的HTML结构:

    <div id="div1" class="style1" lang="en" title="div"></div>

当DOM加载后,表示HTML div元素的变量divElement就会自动生成一个关联集合,它以名值对形式检索这些属性:

    divElement.attributes = {
        id : "div1",
        class : "style1",
        lang : "en",
        title : "div"
    }

在传统DOM中,常用点语法通过元素直接访问HTML属性,如img.src、a.href等,这种方式虽然不标准,但是获得了所有浏览器的支持。

【示例2】img元素拥有src属性,所有图像对象都拥有一个src脚本属性,它与HTML的src特性关联在一起。下面两种用法都可以很好地工作在不同浏览器中:

    <img id="img1" src="" />
    <script>
    var img = document.getElementById("img1");
    img.setAttribute("src","http:// www.w3.org/");        //HTML属性
    img.src = "http:// www.w3.org/";                      //JavaScript属性
    </script>

类似的还有onclick、style和href等。为了保证JavaScript脚本在不同浏览器中都能很好地工作,建议采用标准用法会更为稳妥,而且很多HTML属性并没有被JavaScript映射,所以也就无法直接通过脚本属性进行读写。

5.2、读取属性值

使用元素的getAttribute()方法可以读取指定属性的值,用法如下:

    getAttribute(name)

参数name表示属性名称。

注意:使用元素的attributes属性、getAttributeNode()方法可以返回对应属性节点。

【示例1】访问红色盒子和蓝色盒子,然后读取这些元素所包含的id属性值:

    <div id="red">红盒子</div>
    <div id="blue">蓝盒子</div>
    <script>
    var red = document.getElementById("red");        //获取红色盒子
    console.log(red.getAttribute("id"));             //显示红色盒子的id属性值
    var blue = document.getElementById("blue");      //获取蓝色盒子
    console.log(blue.getAttribute("id"));            //显示蓝色盒子的id属性值
    </script>

【示例2】HTML DOM支持使用点语法读取属性值,使用比较简便,也获得所有浏览器的支持:

    var red = document.getElementById("red");
    console.log(red.id);
    var blue = document.getElementById("blue");
    console.log(blue.id);

注意:对于class属性,则必须使用className属性名,因为class是JavaScript语言的保留字。对于for属性,则必须使用htmlFor属性名,这与CSS脚本中float和text属性被改名为cssFloat和cssText是一个道理。

5.3、设置属性值

使用元素的setAttribute()方法可以设置元素的属性值,用法如下:

    setAttribute(name,value)

参数name和value分别表示属性名和属性值。属性名和属性值必须以字符串的形式进行传递。如果元素中存在指定的属性,它的值将被刷新;如果不存在,则setAttribute()方法将为元素创建该属性并赋值。

【示例1】分别为页面中的div元素设置title属性:

    <div id="red">红盒子</div>
    <div id="blue">蓝盒子</div>
    <script>
    var red = document.getElementById("red");       //获取红盒子的引用
    var blue = document.getElementById("blue");     //获取蓝盒子的引用
    red.setAttribute("title", "这是红盒子");        //为红盒子对象设置title属性和值
    blue.setAttribute("title", "这是蓝盒子");       //为蓝盒子对象设置title属性和值
    </script>

【示例2】可以通过快捷方法设置HTML DOM文档中元素的属性值:

    <label id="label1">文本框:
        <input type="text" name="textfield" id="textfield" />
    </label>
    <script>
    var label = document.getElementById("label1");
    label.className="class1";
    label.htmlFor="textfield";
    </script>

5.4、删除属性

使用元素的removeAttribute()方法可以删除指定的属性,用法如下:

    removeAttribute(name)

参数name表示元素的属性名。

【示例】演示动态设置表格的边框:

    <script>
    window.onload = function() {                               //绑定页面加载完毕时的事件处理函数
        var table = document.getElementsByTagName("table")[0]; //获取表格外框的引用
        var del = document.getElementById("del");              //获取删除按钮的引用
        var reset = document.getElementById("reset");          //获取恢复按钮的引用
        del.onclick = function(){                              //为删除按钮绑定事件处理函数
            table.removeAttribute("border");                   //移出边框属性
        }
        reset.onclick = function(){                            //为恢复按钮绑定事件处理函数
            table.setAttribute("border", "2");                 //设置表格的边框属性
        }
    }
    </script>
    <table width="100%" border="2">
        <tr>
            <td>数据表格</td>
        </tr>
    </table>
    <button id="del">删除</button><button id="reset">恢复</button>

在上面示例中,设计了两个按钮,并分别绑定不同的事件处理函数。单击“删除”按钮即可调用表格的removeAttribute()方法清除表格边框,单击“恢复”按钮即可调用表格的setAttribute()方法重新设置表格边框的粗细。

5.5、使用类选择器

HTML5为document对象和HTML元素新增了getElementsByClassName()方法,使用该方法可以选择指定类名的元素。getElementsByClassName()方法可以接收一个字符串参数,包含一个或多个类名,类名通过空格分隔,不分先后顺序,方法返回带有指定类的所有元素的NodeList。

浏览器支持状态:IE 9+、Firefox 3.0+、Safari 3+、Chrome和Opera 9.5+。

如果不考虑兼容早期IE浏览器或者怪异模式,用户可以放心使用。

【示例】使用document.getElementById(“box”)方法先获取

,然后在它下面使用getElementsByClassName(“blue red”),选择同时包含red和blue类的元素:

    <div id="box">
        <div class="blue red green">blue red green</div>
    </div>
    <div class="blue red  black">blue red  black</div>
    <script>
    var divs = document.getElementById("box").getElementsByClassName("blue red");
    for(var i=0; i<divs.length;i++){
        console.log(divs[i].innerHTML);
    }
    </script>

在document对象上调用getElementsByClassName()会返回与类名匹配的所有元素,在元素上调用该方法就只会返回后代元素中匹配的元素。

6、文档片段

DocumentFragment是一个虚拟的节点类型,仅存在于内存中,没有被添加到文档树中,在网页中看不到渲染效果。使用文档片段的好处:避免浏览器渲染和占用资源。当文档片段设计完善之后,再使用JavaScript一次性添加到文档树中显示出来,这样可以提高效率。

文档片段的主要特征:nodeType值等于11、nodeName等于"#document-fragment"、nodeValue等于null、parentNode等于null。

创建文档片段的方法:

    var fragment = document.createDocumentFragment();

使用appendChild()或insertBefore()方法可以把文档片段添加到文档树中。

每次使用JavaScript操作DOM,都会改变页面呈现,并触发整个页面重新渲染(回流),从而消耗系统资源。为解决这个问题,可以先创建一个文档片段,把所有的新节点附加到文档片段上,最后再把文档片段一次性添加到文档中,从而减少页面重绘的次数。

【示例】使用文档片段创建主流Web浏览器列表:

    <ul id="ul"></ul>
    <script>
    var element  = document.getElementById('ul');
    var fragment = document.createDocumentFragment();
    var browsers = ['Firefox', 'Chrome', 'Opera', 'Safari', 'Internet Explorer'];
    browsers.forEach(function(browser) {
        var li = document.createElement('li');
        li.textContent = browser;
        fragment.appendChild(li);    //此处往文档片段插入子节点,不会引起回流
    });
    element.appendChild(fragment);   //将打包好的文档片段插入ul节点
    </script>

上面示例准备为ul元素添加5个列表项。如果逐个添加列表项,将会导致浏览器反复渲染页面。为避免这个问题,可以使用一个文档片段保存创建的列表项,然后再一次性地将它们添加到文档中,这样能够提升系统的执行效率。

7、CSS选择器

Selectors API是由W3C发布的一个事实标准,为浏览器实现原生的CSS选择器。

  • Selector API level 1(http://www.w3.org/TR/selectors-api/)的核心是两种方法:querySelector()和querySelectorAll()。在兼容浏览器中可以通过文档节点或元素节点调用。目前,已完全支持Selectors API Level 1的浏览器有IE 8+、Firefox 3.5+、Safari 3.1+、Chrome和Opera 10+。
  • Selector API level 2(http://www.w3.org/TR/selectors-api2/)规范为元素增加matchesSelector()方法,这个方法接收一个CSS选择符参数。如果调用的元素与该选择符匹配,则返回true,否则返回false。目前,浏览器对其支持不是很好。

querySelector()和querySelectorAll()方法的参数必须是符合CSS选择符语法规则的字符串,其中querySelector()返回一个匹配元素,querySelectorAll()返回一个匹配集合。

【示例1】新建网页文档,输入下面的HTML结构代码:

    <div class="content">
        <ul>
            <li>首页</li>
            <li class="red">财经</li>
            <li class="blue">娱乐</li>
            <li class="red">时尚</li>
            <li class="blue">互联网</li>
        </ul>
    </div>

如果要获得第一个li元素,可以使用如下方法:

    document.querySelector(".content ul li");

如果要获得所有li元素,可以使用如下方法:

    document.querySelectorAll(".content ul li");

如果要获得所有class为red的li元素,可以使用如下方法:

    document.querySelectorAll("li.red");

提示:DOM API模块包含getElementsByClassName()方法,使用该方法可以获取指定类名的元素。例如:

    document.getElementsByClassName("red");

注意,getElementsByClassName()方法只能够接收字符串且为类名,而不需要加点号前缀,如果没有匹配到任何元素则返回空数组。

CSS选择器是一个便捷的确定元素的方法,这是因为大家已经对CSS很熟悉了。当需要联合查询时,使用querySelectorAll()更加便利。

【示例2】在文档中一些li元素的class名称是red,另一些class名称是blue,可以用querySelectorAll()方法一次性地获得这两类节点:

    var lis = document.querySelectorAll("li.red, li.blue");

如果不使用querySelectorAll()方法,那么要获得同样列表,需要选择所有的li元素,然后通过迭代操作过滤不需要的列表项目。

    var result = [], lis1 = document.getElementsByTagName('li'), classname = '';
    for(var i = 0, len = lis1.length; i < len; i++) {
        classname = lis1[i].className;
        if(classname === 'red' || classname === 'blue') {
            result.push(lis1[i]);
        }
    }

比较上面两种不同的用法,使用选择器querySelectorAll()方法比使用getElementsByTagName()方法要快很多。因此,如果浏览器支持document.querySelectorAll(),那么最好使用它。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值