JavaScript(04): BOM和DOM
来源:互联网 发布:淘宝如何分销 编辑:程序博客网 时间:2024/04/29 09:21
先说明一个问题,到底是将JavaScript内嵌在HTML页面中还是做成外部文件?关于这一点并没有什么必须遵循的规则,但是通常大量的JavaScript代码不应该内嵌在HTML页面中,原因如下:
- 安全性:如果每个人都可以随便查看页面的源代码,那么就有可能会发现安全漏洞从而危及整个站点或应用程序的安全。
- 代码维护:如果每个页面都写自己的JavaScript,那么代码维护将是一场噩梦,而且也不利于对代码的重用。
- 缓存:浏览器通常会根据特定的设置缓存所有的外部JavaScript文件,这意味着如果多个页面使用同一个文件,那么该文件只需要下载一次,这将节省时间和网络带宽。
1. BOM
探讨JavaScript就不能不说到BOM(浏览器对象模型),它提供了独立于内容而与浏览器窗口进行交互的对象。window对象表示整个浏览器窗口,通过它可以对浏览器进行各种操作,包括移动或调整浏览器窗口的大小等。
- moveBy(dx, dy):将浏览器窗口水平移动dx个像素,垂直移动dy个像素。
- moveTo(x, y):将浏览器窗口移到屏幕的(x, y)处。
- resizeBy(dw, dh):将浏览器窗口宽度调整dw个像素,高度调整dh个像素。
- resizeTo(w, h):将浏览器窗口宽度设置为w,高度设置为h,此方法不能使用负数作为参数。
- IE提供了window.screenLeft和window.screenTop对象来判断窗口的位置,但是没有提供判断窗口大小的方法。通过document.body.offsetWidth和document.body.offsetHeight可以获得HTML页面区域的大小,这些都不是标准属性。
- Mozilla、Opera和Safari提供了window.screenX和window.screenY属性判断窗口的位置。除此之外,还提供了window.innerWidth和window.innerHeight属性来判断页面区域的大小以及window.outerWidth和window.outerHeight来判断浏览器窗口的大小。
通过window.open()方法可以打开新窗口,但是由于这种弹出式的窗口通常都被认为是令人厌恶的广告,于是乎很多浏览器都提供了拦截弹出窗口的功能,因此关于此方法不做过多的解释。
window对象的alert()、confirm()和prompt()方法可以产生系统对话框,分别警告框、确认框和输入框,而且都是模态(modal)对话框。
通过window对象的status属性和defaultStatus属性可以操作浏览器窗口的状态栏,但是专业的Web站点通常也不会用JavaScript去操作状态栏,因为它会分散用户的注意力而且不产生实用价值,虽然很多业余人士喜欢在状态栏制作一些跑马灯效果,但是很明显这种效果不仅没用还很让人讨厌,极其的不专业。最主要的是,很多浏览器已经没有状态栏了,比如FireFox和Chrome。
对于熟悉Java的开发者来说,可以使用对象的wait()方法使得程序暂停或者等待指定的时间后才继续执行。这种功能经常都会用到,然后JavaScript中并没有相应的支持。在JavaScript中可以通过window对象的setTimeout()方法设置暂停,或者说指定在将来的某个时间执行某项操作,可以通过clearTimeout()清除暂停。除此之外,window对象还提供了setInterval()方法可以指定某项操作按照指定的时间间隔周期性的执行,同样也可以通过clearInterval()将其取消。
window对象的history属性代表了访问浏览器窗口的历史。该对象提供了forward()、back()和go()方法实现历史页面的前进和后退功能。
我们最熟悉的document对象实际上也是window对象的属性,document对象有很多的属性和方法,这些可以查询参考手册获得相关信息,其中write()和writeln()方法可以在页面中输出内容,但是需要注意的是:必须在完全载入页面前调用write()和writeln()方法,如果这两个方法中的任何一个在页面载入后被调用,那么整个页面的内容会被抹去然后再输出方法中指定的内容。
window对象的location属性表示载入窗口的URL(简单说就是地址栏),通过该对象的href属性可以修改地址栏的内容,还可以通过该对象的reload()方法重新载入页面。通常应该将reload()方法放在代码的最后一行,因为reload()之后的代码可能执行也可能不执行(与网络延迟和资源加载等因素相关),放在前面可能会导致不确定行为。这里可以展示一个经常使用的效果,页面的延迟跳转
<!DOCTYPE html><html><head><title></title><script type="text/javascript">var counter = 5;var delayGoToURL = function () {document.getElementById("counter").innerHTML = counter;counter--;if(counter == 0) {window.location.href = "http://www.baidu.com";delayGoToURL = function() {};}setTimeout("delayGoToURL()", 1000);}window.onload = delayGoToURL;</script></head><body><h1><span id="counter"></span>秒之后跳转到百度</h1></body></html>
其中第13行重新绑定delayGoToURL函数是为了防止页面不能及时跳转时,计数器会变成0甚至负数的情况。
window对象的navigator属性提供了对浏览器信息的封装,它的appCodeName、appName等属性在对浏览器进行判断和检测时有重要作用,很多时候浏览器兼容性检测都需要用到navigator对象。
可以通过window对象的screen属性获取关于用户屏幕的相关信息:
- availHeight:窗口可以使用的屏幕高度(以像素计)
- availWidth:窗口可以使用的屏幕宽度(以像素计)
- colorDepth:颜色位数
- height:屏幕的高度(以像素计,即纵向分辨率)
- width:屏幕的宽度(以像素计,即横向分辨率)
DOM(文档对象模型)是将整个HTML页面视为一个树形结构,那么DOM树的节点(node)层次是这样的:
- Document---最顶层节点,所有其他节点都是它的子节点
- DocumentType---DTD引用
- DocumentFragment
- Element---表示起始标签和结束标签之间的内容
- Attr---代表一个键值对(不能包含子节点)
- Text---代表XML文档中在其实标签和结束标签之间的普通文本(不能包含子节点)
- CDataSection
- Entity
- ProcessingInstruction
- Comment
- Notation
- nodeName --- String --- 节点的名字
- nodeValue --- String ---节点的值
- nodeType --- Number --- 节点类型对应的常量值
- 1 --- Node.ELEMENT_NODE
- 2 --- Node.ATTRIBUTE_NODE
- 3 --- Node.TEXT_NODE
- 9 --- Node.DOCUMENT_NODE
- ownerDocument --- Document --- 指向节点所属的文档
- firstChild --- Node --- 子节点中的第一个节点
- lastChild --- Node --- 子节点中的最后一个节点
- childNodes --- NodeList --- 所有子节点列表
- previousSibling --- Node --- 前一个兄弟节点
- nextSibling --- Node --- 后一个兄弟节点
- hasChildNodes() --- Boolean --- 是否包含一个或多个子节点
- attributes --- NamedNodeMap --- 元素的属性
- appendChild(node) --- Node --- 追加子节点
- removeChild(node) --- Node --- 删除子节点
- replaceChild(newnode, oldnode) --- Node --- 替换子节点
- insertBefore(newnode, refnode) --- Node --- 插入子节点
要访问<html />元素,可以使用document.documentElement属性(在IE 5.5中存在错误),例如:
var html = document.documentElement;var head = html.firstChild; // <head />var body = html.lastChild; // <body />alert(body.nodeName); // BODYalert(body.nodeType); // 1 --- Node.ELEMENT_NODE
当然,也可以通过document.body访问<body />元素。
Element节点的attributes属性其实是NamedNodeMap,提供了用于访问和处理其内容的方法:
- getNamedItem(name):返回nodeName属性值等于name的节点。
- removeNamedItem(name):删除nodeName属性值等于name的节点。
- setNamedItem(node):将node添加到列表中,按其nodeName属性进行索引。
- item(pos):像NodeList一样,返回位置在pos的节点。
<!DOCTYPE html><html><head><title></title></head><body><p style="color:red" id="test">Hello</p><script type="text/javascript">var p = document.getElementsByTagName("p")[0];alert(p.attributes.getNamedItem("id").value); // test</script></body></html>
如果要访问指定节点,可以通过以下方法实现:
- getElementsByTagName():此方法当参数为”*“时可以返回所有元素,但是在低版本的IE(IE6-)中不被支持(可以通过document.all替代)。
- getElementsByName():这个方法通过名字取到一组元素,例如在制作复选框效果(全选、反选)的时候该方法就特别有用。
<!DOCTYPE html><html> <head> <title>01.html</title> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <!--<link rel="stylesheet" type="text/css" href="./styles.css">--><script type="text/javascript">function selectAllOrNot(flag) {var x = document.getElementsByName("goodsName");for(var i = 0; i < x. length; i++) {x[i].checked = flag;}}function reverseSelect() {var x = document.getElementsByName("goodsName");for(var i = 0; i < x. length; i++) {x[i].checked = !x[i].checked;}}</script> </head> <body> <a href="javascript:selectAllOrNot(true)">全选</a> <a href="javascript:reverseSelect()">反选</a> <a href="javascript:selectAllOrNot(false)">取消</a> <table> <tr> <td style="width:25px"></td> <td>商品名称</td> <td>商品价格</td> </tr> <tr> <td><input type="checkbox" name="goodsName"/></td> <td>篮球</td> <td>98.5</td> </tr> <tr> <td><input type="checkbox" name="goodsName"/></td> <td>矿泉水</td> <td>1.5</td> </tr> <tr> <td><input type="checkbox" name="goodsName"/></td> <td>方便面</td> <td>2.3</td> </tr> <tr> <td><input type="checkbox" name="goodsName"/></td> <td>自行车</td> <td>4500</td> </tr> </table> </body></html>
- getElementById():不解释,但是在IE 6中存在bug,使用低版本IE时需要小心。
- createElement() / createTextNode() / appendChild()
<!DOCTYPE html><html><head><title></title><script type="text/javascript">function createMessage() {var p = document.createElement("p");p.style.fontSize = "32px";p.style.fontFamily = "Times New Roman";p.style.fontWeight = "bolder";var text = document.createTextNode("Hello, world!");p.appendChild(text);document.body.appendChild(p);}</script></head><body onload="createMessage()"></body></html>
- removeChild() / replaceChild() / insertBefore()
<!DOCTYPE html><html><head><title></title><script type="text/javascript">function replaceMessage() {var op = document.getElementsByTagName("p")[0];var np = document.createElement("p");var style = document.defaultView.getComputedStyle(op, null);np.style.fontSize = style.fontSize;np.style.fontFamily = style.fontFamily;var text = document.createTextNode("Goodbye, world!");np.appendChild(text);op.parentNode.replaceChild(np, op);}</script></head><body onload="replaceMessage()"><p style="font-size:32px;font-family:Times New Roman">Hello, world!</p></body></html>
[重要提示]:所有的DOM操作必须在页面完全载入之后才能进行。当页面正在载入时,要向DOM插入相关代码是不可能的,因为在页面完全下载到客户端浏览器之前是无法构建完整的DOM树的。为此最好使用onload事件句柄来执行DOM操作的代码。
Web页面开发时经常会用到对表格的处理操作,操作表格可以使用下面的属性和方法:
- caption:表标题<caption />
- tBodies:表身<tbody />
- tFoot:表尾<tfoot />
- tHead:表头<thead />
- rows:表格中所有的行
- createTHead() / createTFoot() / createCaption() / deleteTHead() / deleteTFoot() / deleteCaption()
- deleteRow(pos):删除表格中指定位置的行
- insertRow(pos):在表格指定位置插入新行
- cells:表格中的所有单元格
- deleteCell(pos):删除行中指定位置的单元格
- insertCell(pos):在行的指定位置插入单元格
<!DOCTYPE html><html> <head> <title>01.html</title> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <style type="text/css"> td { width: 75px; } </style> <!--<link rel="stylesheet" type="text/css" href="./styles.css">--><script type="text/javascript">function $(id) {return document.getElementById(id);}function init() {var myRows = $("carts").rows;for(var i = 1; i < myRows.length - 1; i++) {myRows[i].id = "row" + i;myRows[i].cells[4].innerHTML = "<input type=\"button\" value=\"删除\" onclick=\"deleteRow('" + myRows[i].id + "')\" />";myRows[i].cells[5].innerHTML = "<input type=\"button\" value=\"修改\" onclick=\"editRow('" + myRows[i].id + "')\" />";}calcTotal();}function calcItem() {var myRows = $("carts").rows;for(var i = 1; i < myRows.length - 1; i++) {var total = myRows[i].cells[1].innerHTML * myRows[i].cells[2].innerHTML;var totalDisplay = Math.round(total * 10) / 10;myRows[i].cells[3].innerHTML = totalDisplay;}calcTotal();}function calcTotal() {var myRows = $("carts").rows;var sum = 0;for(var i = 1; i < myRows.length - 1; i++) {var totalDisplay = myRows[i].cells[3].innerHTML;sum += parseFloat(totalDisplay);}var lastRow = myRows[myRows.length - 1];lastRow.cells[1].innerHTML = "¥" + sum;}function deleteRow(rowId) {$("carts").deleteRow($(rowId).rowIndex);calcTotal();}function editRow(rowId) {var cell = $(rowId).cells[2];cell.innerHTML ="<input type='text' size='4' value='" + cell.innerHTML + "'/>";var button = $(rowId).cells[5].firstChild;button.setAttribute("value", "保存");button.setAttribute("onclick", "saveRow('" + rowId + "')");}var reg = /^\d+$/;function saveRow(rowId) {var cell = $(rowId).cells[2];if(reg.test(cell.firstChild.value)) {cell.innerHTML = cell.firstChild.value;var button = $(rowId).cells[5].firstChild;button.setAttribute("value", "修改");button.setAttribute("onclick", "editRow('" + rowId + "')");calcItem();}else {alert("请输入正整数");}}window.onload = function() {init();calcItem();};</script> </head> <body> <div align="center"> <table id="carts" style="border-style:solid; border-left-color: black"> <tr> <td>商品名称</td> <td>商品价格</td> <td>商品数量</td> <td align="right">小结</td> <td colspan="2"></td> </tr> <tr> <td>篮球</td> <td>98.5</td> <td onclick="foo(this)">3</td> <td align="right"></td> <td></td> <td></td> </tr> <tr> <td>矿泉水</td> <td>1.5</td> <td>10</td> <td align="right"></td> <td></td> <td></td> </tr> <tr> <td>方便面</td> <td>2.3</td> <td>12</td> <td align="right"></td> <td></td> <td></td> </tr> <tr> <td>自行车</td> <td>4500</td> <td>2</td> <td align="right"></td> <td></td> <td></td> </tr> <tr> <td width="100">总计</td> <td colspan="3" align="right"></td> <td colspan="2"></td> </tr> </table> </div> </body></html>
遍历所有节点的方法
DOM Level 2中提供了遍历DOM的接口(至于你的浏览器到底支持哪种级别的DOM,这个需要去查一下,反正IE支持的DOM级别应该是很低的),下面通过一个例子简单的说明一下
<!DOCTYPE html><html><head><title></title><script type="text/javascript">function foo() {var walker = document.createTreeWalker(document.documentElement, NodeFilter.SHOW_ELEMENT, null, false);var oNode = walker.nextNode();var output = "";while(oNode) {output += oNode.tagName + "\n";oNode = walker.nextNode();}alert(output);}window.onload = foo;</script></head><body><h1>Hello, world!</h1></body></html>
在Chrome和FireFox中运行的结果为:
- JavaScript(04): BOM和DOM
- 【JavaScript】BOM和DOM
- javascript-BOM和DOM
- JavaScript中的Bom和Dom
- javascript中的BOM和DOM
- JavaScript中的DOM和BOM
- 深入解读JavaScript中BOM和DOM
- javascript里的DOM和BOM
- JavaScript BOM和DOM操作教程
- javascript中bom和dom的区别
- javaScript----BOM和DOM的学习
- JavaScript里面的DOM和BOM
- JavaScript教程之DOM和BOM
- 深入解读JavaScript中BOM和DOM
- 浅谈JavaScript的BOM和DOM
- JavaScript、ECMAScript、DOM和BOM对象
- javaScript中DOM和BOM--基础二
- JavaScript中的BOM对象和DOM对象
- MyBatis学习 之 一、MyBatis简介与配置MyBatis+Spring+MySql
- 无题
- Qt layout里面控制控件大小
- JavaScript(03): 面向对象
- JavaScript(02): ECMAScript基础
- JavaScript(04): BOM和DOM
- JavaScript(05): 正则表达式
- hdu 1041
- 推广应用的App签名档和App widget
- 黑马程序员_Java中Class类工作原理详解
- 黑马程序员_基准
- jdbcTemplate 执行 存储过程
- 黑马程序员_线程的安全和非安全
- 函数的初学(1) 定义