事件流 描述的是从页面中接受事件的顺序。
事件冒泡:即事件最开始由最具体的元素(文档中嵌套层次最深的那个节点)接受,然后逐级向上传播至最不具体的那个节点(文档)。 事件捕获:不太具体的节点应该更早接受到事件,而最具体的节点最后接受到事件。
事件处理程序
HTML 事件处理程序: button onclick=”showTextModel()”
DOM0 级事件处理程序: var btn = document.getElementById(“btn”); btn.onclick = function(){} btn.onclick = null;//删除事件
DOM2 级事件处理程序:addEventListener() 和 removeEventListener。参数:处理事件名、处理事件程序、布尔值。true 事件捕获时触发,false 事件冒泡时触发。
IE 事件处理程序:attachEvent() 添加事件 detachEvent 删除事件 参数:处理史建明、处理事件程序。IE8 以及更早的浏览器版本只支持事件冒泡。
跨浏览器的事件处理程序
1 2 3 4 5 6 7 8 9 10 11 var eventUtil = { addHandler: function (element, type , handler ) { if (element.addEventlistener){ element.addEventlistene(type,handler,false ); }else if (element.attachEvent){ element.attachEvent('on' +type,handler); }else { element['on' +type] = handler } } }
事件对象 在触发 DOM 上的事件时都会产生一个对象
事件对象 event DOM 中的事件对象 type 属性:用于获取事件类型 target 属性:用于获取事件目标 offsetWidth 属性:水平方向 width + 左右padding + 左右border-width clientWidth 属性:水平方向 width + 左右padding stopPropagation()方法 用于阻止事件冒泡 preventDefault()方法 阻止事件的默认行为
IE 中的事件对象 type 属性:用于获取事件类型 srcElement属性:用于获取事件目标 window.event cancelBubble 属性 用于阻止事件冒泡 true 阻止事件冒泡 false 不阻止事件冒泡 returnValue 属性 用于阻止事件的默认行为 true 阻止事件默认行为 false 不阻止事件默认行为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 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; } }, 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 ; } }, getEvent:function (event ) { return event?event:window .event; }, 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 ; } } }
事件类型 鼠标事件
click 点击
dblclick 双击
mouseover、mouseout 鼠标移入、移除
mouseenter、mouseleave 鼠标移入、移除
键盘事件
keyDown 按下键盘上任意键时触发
keyUp 释放键盘上的键时触发
keyPress 按下键盘上字符键时触发
节点 节点的类型
文档片段节点
1 2 3 4 5 var frag = document .createDocumentFragment();var li = document .createElement("li" );li.innerHTML = "List item " ; frag.appendChild(li); document .getElementById("list-node" ).appendChild(frag)
判断节点类型
1 2 3 4 5 6 7 8 var containerElement = document .getElementById("container" );containerElement.nodeType == Node.ELEMENT_NODE containerElement.nodeType == 1 containerElement.nodeName == 'div' containerElement.nodeValue == 'Falldown' containerElement.attributes[0 ] containerElement.childNodes[0 ] document .doctype
元素节点的判断
isElement() 判定是否为元素节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 var testDiv = document .createElement("div" );var isElement = function (obj ) {if (obj && obj.nodeType === 1 ) { if (window .Node && obj instanceof Node) { return true ; } try { testDiv.appendChild(obj); testDiv.removeChild(obj); } catch (e) { return false ; } return true ; } return false ; }; isElement(document .getElementByID("test" ));
isHTML 判断是不是 HTML 节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 var testDiv = document .createElement('div' );var isElement = function (obj ) {if (obj && obj.nodeType === 1 ) { if ( window .Node && (obj instanceof Node )){ return true ; } try { testDiv.appendChild(obj); testDiv.removeChild(obj); } catch (e) { return false ; } return true ; } return false ; } var isHTMLElement (el ) { if (isElement){ return isXML(el.ownerDocument); } return false ; }
isXML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 var isXML = function (elem ) {var documentElement = elem && (elem.ownerDocument || elem).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false ; }; console .log(isXML(document .getElementById("test" )));try { var doc = document .implementation.createDocument(null , "HTML" , null ); console .log(doc.documentElement); console .log(isXML(doc)); } catch (e) { console .log("不支持creatDocument方法" ); } var isXML = function (document ) {return ( !!document .xmlVersion || !!document .xml || toString.call(document ) == "[object XMLDocument]" || (document .nodeType == 9 && document .documentElement.nodeName != "HTML" )); }; var isXML = window .HTMLDocument? function (doc ) { return !(doc instanceof HTMLDocument); } : function (doc ) { return "selectNodes" in doc; }; var isXML = function (doc ) { return (doc.createElement("p" ).nodeName !== doc.createElement("P" ).nodeName); };
contains 判断是否是其子节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 var pNode = document .getElementById("p-node" ); var cNode = document .getElementById("c-node" ).childNodes[0 ]; alert(pNode.contains(cNode)); function fixContains (a, b ) { try { while ((b = b.parentNode)){ if (b === a){ return true ; } } return false ; } catch (e) { return false ; } } var pNode = document .getElementById("p-node" );var cNode = document .getElementById("c-node" ).childNodes[0 ];alert(fixContains(pNode, cNode));
浏览器渲染引擎的基本渲染流程 解析 HTML 构建 DOM 树(构建 DOM 节点) -> 构建渲染树(解析样式信息) -> 布局渲染树(布局 DOM 节点) -> 绘制渲染树(绘制 DOM 节点)
domReady
domReady 实现策略 在页面的 DOM 树创建完成后(也就是 HTML 解析第一步完成)即触发,而无需等待其他资源的加载。即 DOMReady 实现策略: 1、支持 DOMContentLoaded 事件的,就使用 DOMContentLoaded 事件 2、不支持的,就用来自 Diego Perini 发现的著名 Hack 兼容。兼容原理大概就是,通过 IE 中的 document.docuemntElement.doScroll(‘left’) 来判断 DOM 树是否创建完毕。
实现 domReady 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 function myReady (fn ) { if ( document .addEventListener ) { document .addEventListener("DOMContentLoaded" , fn, false ); } else { IEContentLoaded(fn); } function IEContentLoaded (fn ) { var d = window .document; var done = false ; var init = function ( ) { if (!done) { done = true ; fn(); } }; (function ( ) { try { d.documentElement.doScroll('left' ); } catch (e) { setTimeout (arguments .callee, 50 ); return ; } init(); })(); d.onreadystatechange = function ( ) { if (d.readyState == 'complete' ) { d.onreadystatechange = null ; init(); } } } }
DOM 节点继承层次
HTML 嵌套规则 HTML存在许多种类型的标签,有的标签下面只允许特定的标签存在,这就叫做 HTML 嵌套规则。
不按 HTML 嵌套规则写,浏览器就不会正确解析,会将不符合嵌套规则的节点放到目标节点的下面,或者变成纯文本。
块状元素:一般是其他元素的容器,可容纳内联元素和其他块状元素,块状元素排斥其他元素与其位于同一行,宽读高度起作用。常见块状元素为 div 和 p。
内联元素:内联元素只能容纳文本或者其他内联元素,它允许其他内联元素与其位于同一行,但宽度高度不起作用。常见内联元素为 a。
块状元素与内联元素嵌套规则
1、块元素可以包含内联元素或某些块元素,但内联元素却不能包含块元素,它只能包含其他内联元素。 2、块元素不能放在 p 元素内。 3、有几个特殊的块级元素只能包含内联元素,不能包含块级元素。:h1 ~ h6 4、块级元素与块级元素并列、内联元素与内联元素并且
相关资料 [视频]DOM事件探秘 √ [视频]DOM探索之基础详解篇 √
盘点HTML字符串转DOM的各种方法及细节
javascript中的offsetWidth、clientWidth、innerWidth及相关属性方法 前端必读:浏览器内部工作原理 [转] 主流JS框架中DOMReady事件的实现 如何检查JavaScript对象是否为DOM对象?
相关代码DOM