1. 动态脚本的添加
动态脚本是指,在页面加载时不存在,当页面加载完毕后,通过 DOM 操作动态添加的脚本。
脚本的添加形式有两种:
通过
<script>
标签的 src 特性引入外部资源
动态加载的外部 JavaScript 文件能够立即执行,比如下面的<script>
元素:<script type="text/javascript" src="test.js"></script>创建这个节点的 DOM 代码如下:
var script = document.createElement("script");script.type = "text/javascript";script.src = "test.js";document.body.appendChild(script);也可以把这个过程封装到一个函数里:
function addScript(url) {var script = document.createElement("script");script.type = "text/javascript";script.src = url;document.body.appendChild(script);}// 然后,可以通过调用这个函数来加载外部脚本文件:addScript("test.js");直接在
<script>
标签中书写脚本代码,也称行内式
比如下面的节点:<script type="text/javascript">function sayHi() {alert("hi");}</script>创建这个节点的 DOM 代码如下:
var script = document.createElement("script");script.type = "text/javascript";script.appendChild(document.createTextNode("function sayHi() {alert('hi');}"));document.dody.appendChild(script);在大多数浏览器中,上面的代码都可以正常执行,但是在 IE 中,则会导致错误。因为 IE 将
<script>
视为一个特殊的元素节点,不允许 DOM 访问其子节点。不过,可以使用<script>
元素的 text 属性来指定 JavaScript 代码,像下面这样:var script = document.createElement("script");script.type = "text/javascript";script.text = "function sayHi() {alert('hi');}";document.body.appendChild(script);下面的方法可以兼容所有的浏览器:
function loadScriptString(code) {var script = document.createElement("script");script.type = "text/javascript";try {script.appendChild(document.createTextNode(code));} catch (error) {script.text = code;}document.body.appendChild(script);}// 然后,可以通过调用这个函数来加载指定的代码loadScriptString("function sayHi() {alert('hi');}");这里,首先尝试标准的 DOM 文本节点方法,除了 IE,其它浏览器都会采用这种方式。如果代码抛出了错误,那么说明是 IE,于是就必须使用 text 属性了。
2. 动态样式的添加
与动态脚本类似,所谓动态样式就是在页面加载的时候不存在,在页面加载完成后动态添加到页面中的样式。
样式的添加同样有两种方法,一种是添加外部样式文件,一种是行内式添加。不过跟脚本不一样的是,两种方法用的元素标签是不一样的。
通过
<link>
标签添加外部样式
我们以下面的这个<link>
元素为例:<link rel="stylesheet" type="text/css" href="test.css">使用 DOM 代码来创建这个元素:
var link = document.createElement("link");link.rel = "stylesheet";link.type = "text/css";link.href = "test.css";var head = document.getElementByTagName("head")[0];head.appendChild(link);整个过程可以用一个函数进行封装:
function loadStyle(url) {var link = document.createElement("link");link.rel = "stylesheet";link.type = "text/css";link.href = url;var head = document.getElementByTagName("head");head.appendChild(link);}// 调用函数加载外部样式loadStyle("test.css");加载外部样式文件的过程是异步的,也就是说加载样式与执行 JavaScript 代码的过程没有固定的次序。
通过
<style>
标签包含嵌入式样式
我们以下面的这个<style>
元素为例:<style rel="stylesheet" type="text/css">body {background-color: red;}</style>使用 DOM 代码来创建这个元素:
var style = document.createElement("style");style.rel = "stylesheet";style.type = "text/css";style.appendChild(document.createTextNode("body {background-color: red;}"));var head = document.getElementByTagName("head");head.appendChild(style);跟
<script>
类似,IE 将<style>
视为一个特殊的元素节点,不允许 DOM 访问其子节点。解决 IE 中的这个问题,需要先访问元素的 styleSheet 属性,然后再访问 styleSheet 属性的 cssText 属性,这个属性可以接受 CSS 代码:function loadStyleString(css) {var style = document.createElement("style");style.rel = "stylesheet";style.type = "text/css";try {style.appendChild(document.createTextNode(css));} catch (error) {style.styleSheet.cssText = css;}var head = document.getElementByTagName("head")[0];head.appendChild(style);// 然后调用这个函数loadStyleString("body{background-color: red}");}这种方式会实时地向页面中添加样式,因此能够马上看到变化。
3. 使用 NodeList、HTMLCollection 和 NamedNodeMap
理解 NodeList、 HTMLCollection 和 NamedNodeMap 这三个集合,是从整体上理解 DOM 的关键。这三个集合都是动态的。每当文档结构发生变化时,它们都会得到更新。因此,它们始终都会保存最新,最准确的信息。从本质上说,执行流每经过一个集合,都会对 DOM 文档实行一次查询,从而获取最新的信息。例如,下面的代码会导致无限循环:
for 循环每进行一次循环前都要对条件 i < divs.length
进行求值,意味着会对文档中所有的 div 元素进行一次查询,然后 i 跟这个新集合的 length 比较。所以虽然 i 在增加,可是 divs.length 同样在实时增加。这个循环会一直进行下去。
如果想要迭代一个这样的集合,最好先将集合的 length 属性初始化一个变量,这样这个变量就保存了一个这个 length 属性的副本。然后让迭代器与该变量进行比较,如下面的例子所示:
一般来说,应该尽量减少访问集合的次数。因为每次访问集合,都会执行一次基于文档的查询。所以,可以考虑将从集合中取得的值缓存起来。