DOM2、DOM3
DOM变化
扩展了API,以满足操作XML的所有需求,提供更好的错误处理。实现了对明明空间的支持。
-
XML命名空间
XHTML支持XML命名空间。
命名空间使用xmlns特性指定,包含着< html >元素中。
样式
-
访问样式
HTML元素在javascript中有个style属性,是CSSStyleDeclaration的实例,包含通过HTML的style特性指定的所有样式,不包含外部样式表或嵌入样式表的样式。
var myDiv = document.getElementById('mydiv')
myDiv.style.backgroundColor = 'red'
myDiv.style.cssFloat = left
为style提供方法和属性
cssText,访问style特性中的css代码
length,获取元素的CSS属性数量
getPropertyValue(propertyName),返回给定属性的字符串值
计算的样式
getComputdeStyle()
接受两个参数:要取得计算样式的元素和一个伪元素字符串,
返回一个CSSStyleDeclaration对象,包含当前元素的所有计算的样式
-
操作样式表
使用CSSStyleSheet类型表示样式表,包括通过< link >元素包含的样式表和在< style >中定义的样式表,但是该类型只读。该表继承于StyleSheet。
document.styleSheets document.styleSheets.length document.sheet //(IE不支持) CSSRule对象,表示样式表中每一条规则 cssText,返回整天规则对应的文本。(IE不支持) parentRule,如果当前规则是导入规则,这个属性引用的就是导入规则 style type
创建规则
insertRule() sheet.insertRule("body {background-color:silver}",0); addRule()(IE8及更早版本)
删除规则
deleteRule() removeRule()
-
元素大小
- 偏移量
-
offsetHeight
- 元素在垂直方向上占用的空间
-
offsetWidth
- 元素在水平方向上占用的空间
-
offsetLeft
- 元素的左外边框至包含元素的左内边框之间的像素距离
-
offsetTop
- 元素的上外边框至包含元素的上内边框之间的像素距离
要知道某个元素在页面上的偏移量,需要将这个元素的offsetLeft和offsetTop与其offsetParent的相同属性相加,循环到根元素。
function getElementLeft(ele){
var actualLeft = ele.offsetLeft;
var current = ele.offsetParent;
while (current !=null){
actualLeft += current.offsetLeft;
current = current.offsetParent
}
return actualLeft;
}
function getElementTop(ele){
var actualTop = ele.offsetTop;
var current = ele.offsetParent;
while (current !=null){
actualTop += current.offsetTop;
current = current.offsetParent
}
return actualTop;
}
- 客户区大小
等于元素内容及其内边距所占空间大小,不计滚动条
clientHeight
clientWidth
function getView(){
if(document.compatMode == "BackCompat"){
return{
width:document.body.clientWidth,
height:document.body.clientHeight
}
}else{
return{
width:document.documentElement.clientWidth,
height:document.documentElement.clientHeight
}
}
}
-
滚动大小
等于包含滚动内容的元素的大小 scrollHeight,没有滚动条情况下,等于元素内容总高度 scrollWidht,没有滚动条情况下,等于元素内容总宽度 scrollLeft,被隐藏在内容区域左侧的像素数 scrollTop,被隐藏在内容区域上方的像素数 在有滚动条时: 在没有滚动条时 IE(标准模式),scrollWidth和ScrollHeight等于文档内容区域, client Width和clientHeight等于视口大小 Opera、Safari、Chrome中,scrollWidth和ScrollHeight等于视口大小, client Width和clientHeight等于文档内容区域
-
确定元素大小
一般来说,right和left差值与offsetWidht相等,bottom和top差值与offsetHeight相等。
-
function getBoundingClientRect(ele){
var scrollTop = document.documentElement.scrollTop;
var scrollLeft = document.documentElement.scrollLeft;
if(ele.getBoundingClientRect){
if(typeof arguments.callee.offset != 'number'){
var temp = document.createElement("div");
temp.style.cssText = "position:absolute;left:0;top:0";
document.body.appendChild(temp);
arguments.callee.offset = -temp.getBoundingClientRect().top-scrollTop;
document.body.removeChild(temp);
temp = null;
}
var rect = ele.getBoundingClientRect();
var offset = arguments.callee.offset;
return {
left:rec.left+offset,
right:rec.right+offset,
top:rec.top+offset,
bottom:rec.bottom+offset,
}
}else{
var actLeft = getElementLeft(ele);
var actTop = getElementTop(ele);
return {
left:actLeft-scrollLeft,
right:actLeft+ele.offsetWidth - scrollLeft,
top:actTop-scrollTop,
bottom:actTop+ele.offsetHeight-scrollTop
}
}
}
遍历
两个类型用来完成顺序遍历(深度优先)DOM结构:NodeIterator和TreeWalker。
- NodeIterator
使用createNodeIterator()方法接受四个参数:
- root:想要作为搜索起点的树中的节点
- whatToShow:表示要访问哪些节点的数字代码
- filter:一个NodeFilter对象
- entityTeferenceExpansion:布尔值,表示是否要扩展实体引用。
var filter = {
accepNode:function(node){
return node.tagName.toLowerCase() == "p"?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP;
}
};
var iterator = document.createNodeIterator(root,NodeFilter.SHOW_ELEMENT,filter,false);
NodeIteratot类型两个主要方法时nextNode和previousNode。
var iterator = document.createNodeIterator(root,NodeFilter.SHOW_ELEMENT,filter,false);
var node = iterator.nextNode();
while(node!==null){
console.log(node.tagName);
node = iterator.nextNode();
}
- TreeWalker
用于遍历的方法:
-next Node()
- previousNode()
- parentNode()
- firstChild()
- lastChild()
- nextSibling()
- previousSibling()
使用createTreeWalker()创建对象
范围
- 用DOM范围实现选择
DOM2中使用createRange()方法创建范围。并且新建的范围直接与创建它的文档关联在一起,不能用于其他文档,然后可以使用范围选择特定部分。
Range类型提供的属性:
- startContainer:范围起点的节点
- startOffset:范围在起点的偏移量
- endContainer:包含范围终点的节点
- endOfffset:范围在
- endContainer中的偏移量
使用selectNode()选择当前元素及其子元素 使用selectNodeContents()选择当前元素中的子元素和文本节点
var range = document.createRange(); range.selectNode(p1);
range.selectNodeContents(p2)
-
用DOM范围实现复杂选择
setStart()和setEnd(),接受两个参数:一个参照节点和一个偏移量值 setStart的参照节点是startContainer,偏移量是startOffset setEnd的参照节点是endContainer,偏移量是endOffset
var range1 = document.createRange();
range2 = document.createRange();
p1 = document.getElementById('p1');
p1Index = -1;
i,len;
for (i=0,len=p1.parentNode.childNodes.length;i<len;i++){
if(p1.parentNode.childNodes[i]==p1){
p1Index = i;
break;
}
}
// 选择这个节点
range1.setStart(p1.parentNode,p1Index);
range1.setEnd(p1.parentNode,p1Index+1);
// 该节点的内容
range2.setStart(p1,0);
range2.setEnd(p1.p1.childNodes.length)
-
操作DOM范围的内容
在创建范围时,内部会为这个范围创建一个文档片段,范围所属的全部节点都被添加到这个文档片段中。 并且不补全缺少的开或闭标签,重新构建有效的DOM结构。然后可以对内容进行操作。
- deleteContents(),从文档中删除范围包含的内容
- cloneContents(),创建范围对象的一个副本,然后在文档其他地方插入该副本。
-
插入DOM范围中的内容
-
insertNode():向范围选区的开始处插入一个节点
-
surroundContents(),环绕范围插入内容,接受参数:环绕范围内容的节点。
提取范围i中的内容 将给定节点插入到文档中原来范围所在的位置上 将文档片段的内容添加到给定节点中
-
-
折叠DOM范围
折叠范围:范围中未选择文档的任何部分。 在折叠范围时,其位置会落在文档中的两个部分之间,可能是范围选区的开始位置,或结束位置。
collapse()
- 复制和清理范围
cloneRange()复制
detach(),从创建范围的文档中分离出该范围,然后解除引用。
事件
事件流
事件流描述从页面中接收事件的顺序。分为事件冒泡和事件捕获
-
事件冒泡
事件开始时由最具体的元素接收,然后主机向上传播到较为不具体的节点。沿着DOM树向上传播
-
事件捕获
事件是从不太具体的节点更早接收到事件,最具体的节点最后接收到事件。事件到达预定目标之前就可捕获。
-
DOM事件流
三个阶段:事件捕获,处于目标阶段和冒泡节点。
事件处理
-
HTML事件处理
例子:
< input type="button" value="Click" οnclick="showMessage()" />
可以通过事件对象event,访问事件的属性等信息
该事件处理的缺点:
HTML与Javascript耦合太大
-
DOM0事件处理
var btn = document.getElementById(“myBtn”);
btn.onclick = function(){
console.log(this);
};在这里插入代码片
这时候的事件处理程序在元素的作用域中运行,this引用当前元素 -
DOM2事件处理
- addEventListener()
- removeEventListener()
- 都接受3个参数:要处理的事件名,作为事件处理程序的函数,布尔值(true为在捕获处理,false表示在冒泡阶段处理)
var btn = document.getElementById("myBtn");
btn.addEventListener("click",function(){
console.log(this.id)
},false)
- IE事件处理
- attachEvent()
- detachEvent()
- 接受参数:事件处理程序名称和事件处理程序函数
事件处理程序在全局作用域运行,this等于window
var btn = document.getElementById("myBtn");
btn.attachEvent('onclick',function(){
alert('Clicked');
});
事件对象
事件对象包含了导致事件的元素、事件的类型以及其他特定事件相关的信息。
-
DOM中的事件对象
event的属性: - bubbles,表示事件是否冒泡 - cancelable,表示是否可以取消事件的默认行为 - currentTarget,事件处理程序当前正在处理事件的那个元素 - defaultPrevented,是否调用preventDefault() detail,细节信息 - eventPhase,事件处理程序的阶段 preventDefault(),取消默认行为 - stopImmediatePropagation(),取消进一步捕获或冒泡,同时阻止任何事件处理程序被调用 target,事件的目标 - type,被触发的事件类型
-
IE中的事件对象
通过window.event获取事件对象
属性:
cancelBubble,取消事件冒泡
returnValue,取消事件的默认行为
serElement,事件的目标
type,被触发的事件类型
事件类型
- UI事件
UI事件值那些不一定与用户操作有关的事件。不一定与DOM规范有关
load,当页面完全加载后在window上面触发
unload,当页面完全卸载后在window上触发
error,当发送js错误时在window上触发
resize,当窗口或框架大小变化时,在window或框架上触发
scroll,当用户滚动滚动条的元素的内容时,在该元素上面触发。
-
焦点事件
blur,在元素失去焦点时触发 DOMFocusIN,元素获得焦点时触发,等价focus,并且冒泡 DOMFocusOut,元素失去焦点时触发,等价blur。 focus,获取焦点时触发,不会冒泡 focusin,元素获得焦点时触发,等价focus,但是冒泡 focusout,元素失去焦点时触发
当焦点从页面一个元素移到另一个元素上,依次触发:
- focusout
- foucusin
- blur
- DOMFocusOut
- focus
- DOMFocusIn
-
鼠标与滚轮事件
click,单击鼠标按钮或回车键触发 dbclick,双击鼠标 mousedown,按下鼠标时触发 mouseenter鼠标光标从原始外部首次移动到元素内时触发 mouseleave,元素上方的鼠标光标移动到元素范围之外时触发 mousemove,鼠标指针在元素内部移动时重复地触发 mouseout,鼠标指针位于元素上方,然后用户将其移入另一个元素时触发 mouseover,鼠标指针在一个元素外部,然后用户将其首次移入另一个元素边界内时触发 mouseup,用户释放鼠标按钮时触发。
除了mouseenter和mouseleave,其他都会冒泡。
双击触发顺序:
mousedown
mouseup
click
mousedown
mouseup
click
dbclick
mousewheel,鼠标滚轮事件
var elem = document.getElemenyById('div0');
var clientX, clientY, isMoving;
var mouseDownHandler = function(event) {
event = event || window.event;
clientX = event.clientX;
clientY = event.clientY;
isMoving = true;
}
var mouseMoveHandler = function(event) {
if (!isMoving) return;
event = event || window.event;
var newClientX = event.clientX,
newClientY = event.clientY;
var left = parseInt(elem.style.left) || 0,
top = parseInt(elem.style.top) || 0;
elem.style.left = left + (newClientX - clientX) + 'px';
elem.style.top = top + (newClientY - clientY) + 'px';
clientX = newClientX;
clientY = newClientY;
}
var mouseUpHandler = function() {
isMoving = false;
}
addEvent(elem, 'mousedown', mouseDownHandler);
addEvent(elem, 'mouseup', mouseUpHandler);
addEvent(elem, 'mousemove', mouseMoveHandler);
-
客户区坐标位置
鼠标事件的视口位置信息保存在clientX和clientY中
-
页面位置坐标
页面坐标保存在pageX和pageY中。 坐标从页面本身而非视口的左边和顶边计算。页面没有滚动时,与clientX、clientY的值相等
var div = document.getElementById("myDiv");
EventUtil.addhandler(div,"click",function(event){
event = EventUtil.getEvent(event);
var pageX = event.pageX;
pageY = event.pageY;
if(pageX === undefined){
pageX = event.clientX + (document.body.scrollLeft ||document.documentElement.scrollLeft)
}
if(pageY === undefined){
pageY = event.clientY + (document.body.scrollTop ||document.documentElement.scrollTop)
}
console.log(pageX,pageY);
})
-
屏幕坐标位置
screenX和screentY属性确定鼠标事件发生时指针相对于整个屏幕的坐标信息
-
相关元素
mouseover事件,主要目标时获得光标的元素,相关元素就是失去光标的元素 mouseout事件,主要目标时失去光标的元素,相关元素时获得光标的元素
-
键盘与文本事件
keydown keypress keyup 按下一个字符键时,触发顺序: keydown(文本框变化之前触发) keypress(文本框变化之前触发) keyup 如果按住不放,就会重复触发keydown和keypress
-
键码
发生keydown和keyup四,event对象的keyCode属性包含一个代码,对于键盘上的键。
-
textInput事件
在可编辑区域中输入字符时,触发这个事件。只会在用户按下能够输入实际字符的键才会被触发。 event对象中包含data属性,里面储存用户输入的字符
-
复合事件
用于处理IME(输入去编辑器)的输入序列。 compositionstart compositionupdate compositionend
-
触摸与手势事件
-
触摸事件
- touchstart,手指触摸屏幕时触发
- touchmove,手指在屏幕滑动时连续触发
- touchend,手指从屏幕上移开时触发
- touchcancel,当系统停止跟踪触摸时触发
- touches,表示当前跟着的触摸操作的Touch对象的数组
- targetTouchs,特定事件目标的touch对象数组
- changeTouches,
上面的Touch对象数组都含有上面的坐标信息
-
手势事件
gesturestart,当一个手指一定按照屏幕上,而另一个手指由触摸屏幕时触发
gesturechange,当触摸屏幕任何一个手指的位置发生变化的触发
gestureend,当任何一个手指从屏幕上面移开时触发
-
内存和性能
添加到页面上的事件处理程序数量直接影响整体运行性能。
首先,每个函数都是对象,占用内存。其次,必须事先制定多余事件处理程序导致DOM访问次数增加,会延迟整个页面的交互就绪时间。
-
事件委托
利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
EventUtil.addHandler(item2,"click",function(event){
alert("I chaange the document`s title");
});
优点:
document对象可以很快访问,而且可以在页面声明周期热火时候为其添加事件处理程序
设置事件处理程序所需的事件更少。至天津一个事件处理程序所需的DOM引用更少,所花时间更少。
占用内存空间更少