第十章:DOM(DOM操作技术)

来源:互联网 发布:go桌面软件下载 编辑:程序博客网 时间:2024/05/22 04:49

  • DOM
    • DOM操作技术
      • 动态脚本
      • 动态样式
      • 操作表格
      • 使用NodeList

DOM

DOM操作技术

  • 很多时候,DOM操作比较简明,因此用JS去生成那些通常由HTML代码生成的内容并不麻烦。不过有些时候,操作DOM并不像表面上那么简单,其中充斥着隐藏的陷阱和不兼容问题。

动态脚本

  • 使用<script>元素可以向页面中插入JavaScript代码,一种方式是通过src特性包含外部文件,另一种方式是用这个元素本身来包含代码。而这里说的动态脚本,是指页面加载时不存在,通过将来的方法调用再引入脚本。看下面的代码:
    function loadScript(url) {        var script = document.createElement("script");        script.type = "text/javascript";        script.src = url;        document.body.appendChild(script);    }    //然后,就可以通过调用这个函数来加载外部的JavaScript元素了。    loadScript("test.js");
  • 加载完成后,就可以在页面的其他地方使用这个脚本了。不过遗憾的是,我们并没有标准方法探知该脚本是否加载完成了,不过有其他的方法(事件),详细看13章。
  • 另外一种动态脚本的书写方式就是直接插入节点的文本。例如:
    function addScript(){        var script = document.createElement("script");        script.type = "text/javascript";        //下面这种方式对除IE浏览器外都有效,因为IE不允许DOM访问script节点的子节点        //script.appendChild(document.createTextNode("function sayHi(){alert('hi');}"));        //下面这种方式仅不支持Safari3.0之前的版本        //script.text = "function sayHi(){alert('hi');}";        //最好的做法:        var code = "function sayHi(){alert('hi');}";        try {            script.appendChild(document.createTextNode(code);        } catch(e) {            script.text = code;        }        document.body.appendChild(script);        sayHi();    }
  • 下面是整合后的代码
    function loadScriptString(code){        var script = document.createElement("script");        script.type = "text/javascript";        try {            script.appendChild(document.createTextNode(code));        } catch (ex){            script.text = code;        }        document.body.appendChild(script);    }    function addScript(){        loadScriptString("function sayHi(){alert('hi');}");        sayHi();    }
  • 实际上这个loadScriptString的效果就是eval类似。。。

动态样式

  • 这个部分其实和上面类似。利用的是<link>标签链接外部css样式,和<style>手写css样式。看一下这两种方式:
    <link rel="stylesheet" type="text/css" href="styles.css">    <style type="text/css">        body {            backgroud-color: red;        }    </style>
  • 触类旁通,知道动态脚本怎么写,动态样式应该也是一目了然了吧?
    function loadStyle(url) {        var link = document.createElement("link");        link.rel = "stylesheet";        link.type = "text/css";        link.href = url;//是href不是src哦        var head = document.getElementsByTagName("head")[0];        head.appendChild(link);    }    loadStyle("test.css");    function loadStyleString(css){        var style = document.createElement("style");        style.type = "text/css";        try{            style.appendChild(document.createTextNode(css));        } catch (ex){            //注意是style.styleSheet.cssText            style.styleSheet.cssText = css;        }        var head = document.getElementsByTagName("head")[0];        head.appendChild(style);    }    loadStyleString("body{background-color:red}"); 
  • 需要注意的是加载样式文件的过程是异步的。一般来说,知不知道样式已经加载完成并不重要,不过也存在几种利用事件来检测这个过程是否完成的技术,在13章讨论。

操作表格

  • <table>元素是HTML中最复杂的结构之一(也经常用到)。如果我们要用脚本去创建该元素(如下),免不了要写大量的代码:
    <table border="1" width="100%">        <tbody>            <tr>                <td>Cell 1,1</td>                <td>Cell 1,2</td>            </tr>            <tr>                <td>Cell 2,1</td>                <td>Cell 2,2</td>            </tr>        </tbody>    </table>
  • 为了方便构建表格,HTML DOM还为<table>、<tbody>、<tr>元素添加了一些属性和方法。
  • <table>元素添加的属性和方法如下:
    1. caption 保存着对<caption>元素(如果有)的指针
    2. tBodies 是一个<tbody>元素的HTMLCollection
    3. tFoot 保存着对<tfoot>元素(如果有)的指针
    4. tHead 保存着对<thead>元素(如果有)的指针
    5. rows 是一个表格所有行的HTMLCollection
    6. createTHead() 创建<thead>元素,将其放到表格中,返回引用
    7. createTFoot() 创建<tfoot>元素,将其放到表格中,返回引用
    8. createCaption() 创建<caption>元素,将其放到表格中,返回引用
    9. deleteTHead() 删除<thead>元素
    10. deleteTFoot() 删除<tfoot>元素
    11. deleteCaption() 删除<caption>元素
    12. deleteRow(pos) 删除指定位置的行
    13. insertRow(pos) 向rows集合中的指定位置插入一行(插入空行,后续再改)
  • <tbody>元素添加的属性和方法如下:
    1. rows 保存着<tbody>元素中行的HTMLCollection
    2. deleteRow(pos) 删除指定位置的行
    3. insertRow(pos) 向rows集合中的指定位置插入一行,返回对新插入行的引用
  • <tr>元素添加的属性和方法如下:

    1. cells 保存着<tr>元素中单元格的HTMLCollection
    2. deleteCell(pos) 删除指定位置的单元格
    3. insertCell(pos) 向指定位置插入单元格,并返回新插入单元格的引用
  • 精简后的代码如下(虽然比一直用createElement方便了很多,但是还是很麻烦!):

    var table = document.createElement("table");    table.border = 1;    table.width = "100%";    var tbody = document.createElement("tbody");    table.appendChild(tbody);    tbody.insertRow(0);    tbody.rows[0].insertCell(0);    tbody.rows[0].cells[0].appendChild(document.createTextNode("cell 1,1"));    tbody.rows[0].insertCell(1);    tbody.rows[0].cells[1].appendChild(document.createTextNode("cell 1,2"));    tbody.insertRow(1);    tbody.rows[1].insertCell(0);    tbody.rows[1].cells[0].appendChild(document.createTextNode("cell 2,1"));    tbody.rows[1].insertCell(1);    tbody.rows[1].cells[1].appendChild(document.createTextNode("cell 2,2"));    document.body.appendChild(table);

使用NodeList

  • 理解NodeList及其”近亲”NamedNodeMap和HTMLCollection,是从整体上透彻理解DOM的关键所在。这三个集合都是”动态”的,换句话说,每当文档得到更新时,他们都会得到更新。从本质上说,所有NodeList对象都是在访问DOM文档时实时运行的查询。例如下面的代码会导致无限循环:
    var divs = document.getElementById("div");    var i,div;    for (i=0;i<divs.childNodes.length;i++) {        div = document.createElement("div");        divs.appendChild(div);    }
  • 其实这个在之前说过了,divs.childNodes.length随着divs.appendChild()的操作是会变化的。浏览器不会将创建的所有集合保存在一个列表里,而是在下一次访问集合时更新集合。可以这么理解,每次调用divs.childNodes.length,相当于在该句之前隐藏了一句var divs = document.getElementById(“div”);
  • 要解决这个问题,最好是使用length属性初始化第二个变量:
    var divs = document.getElementById("div");    var i, div, length;    for (i=0, length=divs.childNodes.length;i<length;i++) {        div = document.createElement("div");        divs.appendChild(div);    }
  • 我们要尽量避免过多访问NodeList对象,因为每次访问都会运行一次基于文档的查询。如果在保证文档不会更新的情况下,我们可以新建一个存放Node对象的数组作为缓存去解决该类问题。
0 0
原创粉丝点击