第11章 DOM(二)

1 DOM 操作技术

1.1 动态脚本

动态加载的外部 JavaScript 文件能够立即运行

<script type="text/javascript" src="client.js"></script>

//整个过程可以使用下面的函数来封装
function loadScript(url){ 
 var script = document.createElement("script"); 
 script.type = "text/javascript"; 
 script.src = url; 
 document.body.appendChild(script); 
}
loadScript("client.js");

另一种指定 JavaScript 代码的方式是行内方式。

<script type="text/javascript"> 
 function sayHi(){ 
 alert("hi"); 
 } 
</script>

//整个过程可以用以下函数来表示:
 var script = document.createElement("script"); 
 script.type = "text/javascript"; 
 try { 
 script.appendChild(document.createTextNode(code)); 
 } catch (ex){ 
 script.text = code; 
 } 
 document.body.appendChild(script); 
} 
loadScriptString("function sayHi(){alert('hi');}");

以这种方式加载的代码会在全局作用域中执行,而且当脚本执行后将立即可用。

1.2 动态样式

动态样式是在页面加载完成后动态添加到页面中的。必须将<link>元素添加到<head>而不是<body>元素(外链式

<link rel="stylesheet" type="text/css" href="styles.css">

//整个过程可以用以下函数来表示
function loadStyles(url){ 
 var link = document.createElement("link");
 link.rel = "stylesheet"; 
 link.type = "text/css"; 
 link.href = url; 
 var head = document.getElementsByTagName("head")[0]; 
 head.appendChild(link); 
}
loadStyles("styles.css");

另一种定义样式的方式是使用<style>元素来包含嵌入式 CSS(内嵌式

<style type="text/css"> 
body { 
 background-color: red; 
} 
</style>

//整个过程可以用以下函数来表示
function loadStyleString(css){ 
 var style = document.createElement("style");
 style.type = "text/css"; 
 try{ 
 style.appendChild(document.createTextNode(css)); 
 } catch (ex){ 
 style.styleSheet.cssText = css; 
 } 
 var head = document.getElementsByTagName("head")[0]; 
 head.appendChild(style); 
}

使用 style 特性定义针对特定元素的样式。(行内式) 

//检测
var supportsDOM2CSS = document.implementation.hasFeature("CSS", "2.0");

1.3 操作表格

 insertRow(pos):向 rows 集合中的指定位置插入一行,返回对新插入行的引用。

 cells:保存着<tr>元素中单元格的 HTMLCollection。

 insertCell(pos):向 cells 集合中的指定位置插入一个单元格,返回对新插入单元格的引用。

1.4 使用NodeList

  • 集合是“动态的”;换句话说,每当文档结构发生变化时,它们都会得到更新
  • 因为每次访问 NodeList,都会运行一次基于文档的查询。所以,可以考虑将从 NodeList 中取得的值缓存起来。DOM 操作往往是 JavaScript 程序中开销最大的部分,最好的办法就是尽量减少 DOM 操作
var divs = document.getElementsByTagName("div"), 
 i, 
 len, 
 div; 
for (i=0, len=divs.length; i < len; i++){ //divs.length 的值在每次循环后都会递增,于 len 中保存着对 divs.length 在循环开始时的一个快照
 div = document.createElement("div"); //既然 i 和 divs.length 每次都会同时递增,结果它们的值永远也不会相等。
 document.body.appendChild(div); 
}

2 样式

2.1 访问元素的样式

  • 对于使用短划线(分隔不同的词汇,例如 background-image)的 CSS 属性名,必须将其转换成驼峰大小写形式(style.backgroundImage ),才能通过 JavaScript 来访问。
  • 只要取得一个有效的 DOM 元素的引用,就可以随时使用 JavaScript 为其设置样式
//设置
var myDiv = document.getElementById("myDiv"); 
//设置背景颜色
myDiv.style.backgroundColor = "red"; 
//改变大小
myDiv.style.width = "100px"; 
myDiv.style.height = "200px"; 
//指定边框
myDiv.style.border = "1px solid black";

//读取
<div id="myDiv" style="background-color:blue; width:10px; height:25px"></div>
alert(myDiv.style.backgroundColor); //"blue" 
alert(myDiv.style.width); //"10px" 
alert(myDiv.style.height); //"25px"

2.1.1 DOM 样式属性和方法 

cssText:通过它能够访问到 style 特性中的 CSS 代码。在写入模式下,赋给 cssText 的值会重写整个style 特性的值。

 length:应用给元素的 CSS 属性的数量。设计 length 属性的目的,就是将其与 item()方法配套使用。

 item(index):返回给定位置的 CSS 属性的名称。

getPropertyCSSValue():返回一个包含两个属性的 CSSValue 对象,这两个属性分别是:cssText 和 cssValueType。其中,cssText 属性的值与 getPropertyValue()返回的值相同,而 cssValueType 属性则是一个数值常量,表示值的类型:0 表示继承的值,1 表示基本的值,2 表示值列表,3 表示自定义的值。

getPropertyValue(propertyName):返回给定属性的字符串值

 removeProperty(propertyName):从样式中删除给定属性。

 setProperty(propertyName,value,priority):将给定属性设置为相应的值,并加上优先权标志("important"或者一个空字符串)。

myDiv.style.cssText = "width: 25px; height: 100px; background-color: green"; 
alert(myDiv.style.cssText);

for (var i=0, len=myDiv.style.length; i < len; i++){ 
 alert(myDiv.style[i]); //或者 myDiv.style.item(i) 
}

2.1.2 计算的样式(只读)

getComputedStyle()方法。两个参数:要取得计算样式的元素和一个伪元素字符串(例 如":after")。返回一个 CSSStyleDeclaration 对象(与 style 属性的类型相同),其中包含当前元素的所有计算的样式

<!DOCTYPE html> 
<html> 
<head> 
 <title>Computed Styles Example</title> 
 <style type="text/css"> 
 #myDiv { //内嵌式
 background-color: blue; 
 width: 100px; 
 height: 200px; 
 } 
 </style> 
</head> 
<body> 
 <!-- 行内式 -->
 <div id="myDiv" style="background-color: red; border: 1px solid black"></div> 
</body> 
</html>

var myDiv = document.getElementById("myDiv"); 
var computedStyle = document.defaultView.getComputedStyle(myDiv, null); 
alert(computedStyle.backgroundColor); // "red" 
alert(computedStyle.width); // "100px" 
alert(computedStyle.height); // "200px" 
alert(computedStyle.border); // 在某些浏览器中是"1px solid black"

IE 中,每个具有 style 属性的元素还有一个 currentStyle 属性。

var myDiv = document.getElementById("myDiv"); 
var computedStyle = myDiv.currentStyle; 

alert(computedStyle.backgroundColor); //"red" 
alert(computedStyle.width); //"100px" 
alert(computedStyle.height); //"200px" 
alert(computedStyle.border); //undefined

2.2 操作样式表

应用于文档的所有样式表是通过 document.styleSheets 集合来表示的。通过这个集合的 length属性可以获知文档中样式表的数量,而通过方括号语法或 item()方法可以访问每一个样式表。从StyleSheet 接口继承而来的属性如下。

href:如果样式表是通过<link>包含的,则是样式表的 URL;否则,是 null。

media:当前样式表支持的所有媒体类型的集合。

type:表示样式表类型的字符串。对 CSS 样式表而言,这个字符串是"type/css"。

var sheet = null; 
for (var i=0, len=document.styleSheets.length; i < len; i++){
 sheet = document.styleSheets[i]; 
 alert(sheet.href); 
}

DOM 规定了一个包含 CSS StyleSheet 对象的属性,名叫 sheet;IE 支持的是 styleSheet 属性。这里的 getStyleSheet()返回的样式表对象与 document.styleSheets 集合中的样式表对象相同

function getStyleSheet(element){ 
 return element.sheet || element.styleSheet; 
} 
//取得第一个<link/>元素引入的样式表
var link = document.getElementsByTagName("link")[0]; 
var sheet = getStylesheet(link);

1. CSS 规则

 selectorText:返回当前规则的选择符文本。

 cssText:返回整条规则对应的文本。

div.box { 
 background-color: blue; 
 width: 100px; 
 height: 200px; 
}

var sheet = document.styleSheets[0]; 
var rules = sheet.cssRules || sheet.rules; //取得规则列表
var rule = rules[0]; //取得第一条规则
alert(rule.selectorText); //"div.box" 
alert(rule.style.cssText); //完整的 CSS 代码
alert(rule.style.backgroundColor); //"blue" 
alert(rule.style.width); //"100px" 
alert(rule.style.height); //"200px"

2. 创建规则

要向现有样式表中添加新规则,需要使用 insertRule()方法。这个方法接受两个参数:规则文本和表示在哪里插入规则的索引。

IE8 及更早版本支持一个类似的方法,名叫 addRule(),两必选参数:选择符文本和 CSS样式信息;一个可选参数:插入规则的位置。

sheet.insertRule("body { background-color: silver }", 0); //DOM 方法
sheet.addRule("body", "background-color: silver", 0); //仅对 IE 有效

//封装
function insertRule(sheet, selectorText, cssText, position){
 if (sheet.insertRule){ 
 sheet.insertRule(selectorText + "{" + cssText + "}", position); 
 } else if (sheet.addRule){ 
 sheet.addRule(selectorText, cssText, position); 
 } 
}
insertRule(document.styleSheets[0], "body", "background-color: silver", 0);

但随着要添加规则的增多,这种方法就会变得非常繁琐。

3. 删除规则

从样式表中删除规则的方法是 deleteRule(),这个方法接受一个参数:要删除的规则的位置。

IE 支持的类似方法叫 removeRule(),使用方法相同。

sheet.deleteRule(0); //DOM 方法
sheet.removeRule(0); //仅对 IE 有效

//封装
function deleteRule(sheet, index){ 
 if (sheet.deleteRule){ 
 sheet.deleteRule(index); 
 } else if (sheet.removeRule){ 
 sheet.removeRule(index); 
 } 
}
deleteRule(document.styleSheets[0], 0);

删除规则也不是实际 Web 开发中常见的做法。

2.3 元素大小

2.3.1 偏移量

所有这些偏移量属性都是只读的,而且每次访问它们都需要重新计算。

 offsetHeight:元素在垂直方向上占用的空间大小,以像素计。包括元素的高度、(可见的)水平滚动条的高度、上边框高度和下边框高度。

 offsetWidth:元素在水平方向上占用的空间大小,以像素计。包括元素的宽度、(可见的)垂直滚动条的宽度、左边框宽度和右边框宽度。

 offsetLeft:元素的左外边框至包含元素的左内边框之间的像素距离

 offsetTop:元素的上外边框至包含元素的上内边框之间的像素距离。

要想知道某个元素在页面上的偏移量,将这个元素的 offsetLeft 和 offsetTop 与其 offsetParent的相同属性相加,如此循环直至根元素,就可以得到一个基本准确的值。

function getElementLeft(element){ 
 var actualLeft = element.offsetLeft; 
 var current = element.offsetParent; 
 while (current !== null){ 
 actualLeft += current.offsetLeft; 
 current = current.offsetParent; 
 } 
 return actualLeft; 
}

2.3.2 客户区大小

客户区大小就是元素内部的空间大小,因此滚动条占用的空间不计算在内。客户区大小也是只读的,也是每次访问都要重新计算的。

clientWidth 属性是元素内容区宽度加上左右内边距宽度;clientHeight 属性是元素内容区高度加上上下内边距高度。

要确定浏览器视口大小,可以使用 document.documentElement 或 document.body(在 IE7 之前的版本中)的clientWidth 和 clientHeight。

function getViewport(){ 
 if (document.compatMode == "BackCompat"){ 
 return { 
 width: document.body.clientWidth, 
 height: document.body.clientHeight 
 }; 
 } else { 
 return { 
 width: document.documentElement.clientWidth, 
 height: document.documentElement.clientHeight 
 }; 
 } 
}

2.3.3 滚动大小

这些属性会在不同浏览器间发现一些不一致性问题。

 scrollHeight:在没有滚动条的情况下,元素内容的总高度

 scrollWidth:在没有滚动条的情况下,元素内容的总宽度。

 scrollLeft:被隐藏在内容区域左侧的像素数。通过设置这个属性可以改变元素的滚动位置。

 scrollTop:被隐藏在内容区域上方的像素数。通过设置这个属性可以改变元素的滚动位置。

在确定文档的总高度时(包括基于视口的最小高度时),必须取得 scrollWidth/clientWidth 和scrollHeight/clientHeight 中的最大值,才能保证在跨浏览器的环境下得到精确的结果。

var docHeight = Math.max(document.documentElement.scrollHeight, 
 document.documentElement.clientHeight); 
var docWidth = Math.max(document.documentElement.scrollWidth, 
 document.documentElement.clientWidth);

此将元素的scrollLeft 和 scrollTop 设置为 0,就可以重置元素的滚动位置

function scrollToTop(element){ 
 if (element.scrollTop != 0){ 
 element.scrollTop = 0; 
 } 
}

2.3.4 确定元素大小

getBoundingClientRect()方法。这个方法返回会一个矩形对象,包含 4 个属性:left、top、right 和 bottom。这些属性给出了元素在页面中相对于视口的位置

3 遍历

DOM 遍历是深度优先 DOM 结构遍历,下图 展示了对以 document 为根节点的 DOM 树进行深度优先遍历的先后顺序。
<!DOCTYPE html> 
<html> 
 <head> 
 <title>Example</title> 
 </head> 
 <body> 
 <p><b>Hello</b> world!</p> 
 </body> 
</html>

NodeIterator 类型,可以使用 document.createNodeIterator()方法创建它的新实例。只允许以一个节点的步幅前后移动
创建 TreeWalker 对象要使用 document.createTreeWalker()方法。还支持在 DOM 结构的 各个方向上移动,包括父节点、同辈节点和子节点等方向。
<div id="div1"> 
 <p><b>Hello</b> world!</p> 
 <ul> 
 <li>List item 1</li> 
 <li>List item 2</li> 
 <li>List item 3</li> 
 </ul> 
</div>

var div = document.getElementById("div1"); 
var iterator = document.createNodeIterator(div, NodeFilter.SHOW_ELEMENT, 
 null, false); 
var node = iterator.nextNode(); //nextNode()方法用于向前前进一步
while (node !== null) { 
 alert(node.tagName); //输出标签名
 node = iterator.nextNode(); 
}

DIV 
P 
B 
UL 
LI 
LI 
LI

var div = document.getElementById("div1"); 
var walker = document.createTreeWalker(div, NodeFilter.SHOW_ELEMENT, null, false); 
walker.firstChild(); //转到<p> :在不同方向上遍历 DOM 结构的方法
walker.nextSibling(); //转到<ul> 
var node = walker.firstChild(); //转到第一个<li> 
while (node !== null) { 
 alert(node.tagName); 
 node = walker.nextSibling(); 
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值