@EncyKe
2015-12-21T04:41:27.000000Z
字数 6506
阅读 2979
前端
JavaScript
DOM:即Document Object Model,文档对象模型;把整个页面映射为一个多层节点树结构。
为了解决netscape和microsoft两家浏览器之间在脚本上相互不兼容的问题,W3C联盟统一制定了DOM标准——
- DOM 0级: NetScape 4-和Microsoft IE 4-洪荒年代DHTML;
- DOM 1级:主要定义了HTML和XML文档的底层结构。由两个模块组成:DOM Core和DOM HTML。DOM Core规定了基于XML的文档结构标准,通过这个标准简化了对文档中任意部分的访问和操作;DOM HTML则在DOM核心的基础上加以扩展,添加了针对HTML的对象和方法;
- DOM 2级:在原来DOM的基础上又扩充了鼠标、用户界面事件、范围、遍历等细分模块,而且通过对象接口增加了对CSS的支持,核心模块也经过扩展开始支持XML命名空间。引入了下列模块,包含了众多新类型和新接口:DOM视图(DOM Views):定义了跟踪不同文档视图的接口、DOM事件(DOM Events):定义了事件和事件处理的接口、DOM样式(DOM Style):定义了基于CSS为元素应用样式的接口、DOM遍历和范围(DOM Traversal and Range):定义了遍历和操作文档树的接口;
- DOM 3级:进一步扩展了DOM,引入了以下模块:DOM加载和保存模块(DOM Load and Save):引入了以统一方式加载和保存文档的方法、DOM验证模块(DOM Validation):定义了验证文档的方法、DOM核心的扩展(DOM Style):支持XML 1.0规范,涉及XML Infoset、XPath和XML Base;
- 通用标记语言 (GML):1969;
- 标准通用标记语言 (SGML):1985;
- 超文本标记语言 (HTML):1993;
- 可扩展标记语言 (XML):1998;
setTimeout()
特点:有闪动,不稳定,体验欠佳;
window.onload =
特点:稳妥,但大量JS存在时体验也是欠佳;
$(document).ready(...);
特点:应用了DOMContentLoaded
及其对IE的hack,兼容性好;
DOMContentLoaded
比onload
要快。
function myReady(fn){
//对于现代浏览器,对DOMContentLoaded事件的处理采用标准的事件绑定方式
if ( document.addEventListener ) {
document.addEventListener("DOMContentLoaded", fn, false);
} else {
IEContentLoaded(fn);
}
//IE模拟DOMContentLoaded
function IEContentLoaded (fn) {
var d = window.document;
var done = false;
//只执行一次用户的回调函数init()
var init = function () {
if (!done) {
done = true;
fn();
}
};
(function () {
try {
// DOM树未创建完之前调用doScroll会抛出错误
d.documentElement.doScroll('left');
} catch (e) {
//延迟再试一次~
setTimeout(arguments.callee, 50);
return;
}
// 没有错误就表示DOM树创建完毕,然后立马执行用户回调
init();
})();
//监听document的加载状态
d.onreadystatechange = function() {
// 如果用户是在domReady之后绑定的函数,就立马执行
if (d.readyState == 'complete') {
d.onreadystatechange = null;
init();
}
}
}
}
共12种,常用7种:
节点类型 | 数值常量 | 字符常量 |
---|---|---|
Element (元素节点) | 1 | ELEMENT_NODE |
Attr (属性节点) | 2 | ATTRIBUTE_NODE |
Text (文本节点) | 3 | TEXT_NODE |
Comment (注释节点) | 8 | COMMENT_NODE |
Document (文档节点) | 9 | DOCUMENT_NODE |
DocumentType (文档类型节点) | 10 | DOCUMENT_TYPE_NODE |
DocumentFragment (文档片段节点) | 11 | DOCUMENT_FRAGMENT_NODE |
element.nodeType
属性返回节点类型返回值可以是数值常量,也可以是字符常量;鉴于数值常量兼容性更加,建议统一使用数值变量作判断。
element.nodeType == Node.ELEMENT_NODE;
// IE不支持;Node未定义。
element.nodeType == 1;
// 兼容性佳;
element.nodeName
返回元素的名称element.nodeValue
设置或返回节点值节点类型 | nodeName | nodeValue |
---|---|---|
Element (元素节点) | 标签名 | null |
Attr (属性节点) | 属性 | 属性值E |
Text (文本节点) | text | 内容文本 |
Comment (注释节点) | comment | 注释文本 |
DocumentType (文档类型节点) | doctype名 | null |
DocumentFragment (文档片段节点) | document-fragment | null |
element.attributes
返回元素属性集合element.childNodes
返回元素子节点的集合isElement
判断是否为元素节点精简版:
var isElement = function (el){
return !!el && el.nodeType === 1;
}
完整版:
var isElement = function (obj) {
if (obj && obj.nodeType === 1) {
//先过滤最简单的
if( window.Node && (obj instanceof Node )){
//如果是IE9,则判定其是否Node的实例
return true;
//由于obj可能是来自另一个文档对象,因此不能轻易返回false
}
try {
//最后以这种效率非常差但肯定可行的方案进行判定
testDiv.appendChild(obj);
testDiv.removeChild(obj);
} catch (e) {
return false;
}
return true;
}
return false;
}
isHTML
判断是否为HTML元素节点严谨版:
var isHTML = function(doc) {
return doc.createElement("p").nodeName === doc.createElement("P").nodeName;
}
isXML
判断是否为XML元素节点精简版:
var isXML = window.HTMLDocument ? function(doc) {
return !(doc instanceof HTMLDocument);
} : function(doc) {
return "selectNodes" in doc;
}
完整版:
var isXML = function(document) {
return (!!document.xmlVersion) || (!!document.xml) || (toString.call(document) == '[object XMLDocument]')
|| (document.nodeType == 9 && document.documentElement.nodeName != 'HTML');
};
严谨版:
var isXML = function(doc) {
return doc.createElement("p").nodeName !== doc.createElement("P").nodeName;
}
contains
(原生) 以及isContains
判断节点包含关系IE下的contains方法只对元素节点起作用;
function isContains(a, b) {
try {
while ((b = b.parentNode)){
if (b === a){
return true;
}
}
return false;
} catch (e) {
return false;
}
}
鉴于继承层次复杂,建议尽量使用现有框架(如MVVM)实现业务。
对象.onclick = null;
addEventListener()
:添加事件监听; removeEventListener()
:删除事件监听;addEventListener('事件名',函数名,布尔值);
; addEventListener()
添加的事件只能通过removeEventListener()
删除;attachEvent()
添加事件监听; detachEvent()
删除事件监听;attachEvent('事件名',函数名);
。
var eventUtil={
// 添加句柄
addHandler:function(element,type,handler){
if(element.addEventListener){
element.addEventListener(type,handler,false);
}else if(element.attachEvent){
element.attachEvent('on'+type,handler);
}else{
element['on'+type]=handler;
// JS下:element.onclick===element['onclick'];
}
},
// 删除句柄
removeHandler:function(element,type,handler){
if(element.removeEventListener){
element.removeEventListener(type,handler,false);
}else if(element.detachEvent){
element.detachEvent('on'+type,handler);
}else{
element['on'+type]=null;
}
}
}
引用示例:eventUtil.addHandler(go,'click',function);
。
type
属性:获取事件类型;target
属性:获取事件目标;event.target.nodeName
获取标签名;stopPropagation()
方法:阻止事件冒泡;preventDefault()
方法:阻止事件的默认行为;type
属性:获取事件类型;srcElement
属性:事件目标;cancelBubble=true
:阻止事件冒泡;returnValue=false
:阻止事件的默认行为;
function getByClass(clsName,parent){
var oParent=parent?document.getElementById(parent):document,
eles=[],
elements=oParent.getElementsByTagName('*');
for(var i=0,l=elements.length;i<l;i++){
if(elements[i].className==clsName){
eles.push(elements[i]);
}
}
return eles;
}
引用示例:getByClass(类名,父级)[0];
父级可加可不加。
var eventUtil={
getEvent:function(event){
return event?event:window.event;
// return event = event || window.event;
// window.event是为IE 8及更早做的兼容;
},
getType:function(event){
return event.type;
},
getElement:function(event){
return event.target || event.srcElement;
},
preventDefault:function(event){
if(event.preventDefault){ // 判断时不能加括号;
event.preventDefault();
}else{
event.returnValue=false;
}
},
stopPropagation:function(event){
if(event.stopPropagation){
event.stopPropagation();
}else{
event.cancelBubble=true;
}
}
}
引用示例:eventUtil.getEvent(event);
。
onkeydown
:按下键盘上任意键时触发(按住不放会重复触发);onkeypress
:按下键盘上的字符键时触发;onkeyup
:释放键盘上的键时触发;
document.onkeyup=function(event){
event = event || window.event;
console.log(event.keyCode);
}