DOM + BOM
DOM 和 BOM 是什么?§
- BOM 浏览器对象模型:根节点是
window
。- navigator 对象:
appCodeName; appName; appVersion; cookieEnabled; platform; userAgent;
。 - screen 对象:
availHeight; availWidth; height; width; colorDepth;
。 - history 对象:
back; forward; go;
。 - location 对象:
- 属性:
hash; host; hostName; href; pathname; port; portocol;
。 - 方法:
assign; reload; replace
。
- 属性:
- document 对象:
- 集合:
anchors; images; links; forms;
。 - 属性:
cookie; domain; referrer; title; URL;
。 - 方法:
open; close; write; writeIn;
。
- 集合:
- 窗口控制:
moveBy; moveTo; resizeBy; resizeTo; scrollBy; scrollTo;
。 - 焦点控制:
focus; blur;
。 - 打开关闭窗口:
open; close;
。 - 定时器:
setTimeout; clearTimeout; setInterval; clearInterval
。 - 对话框:
alert; confirm; prompt;
。 - 属性:
- 状态栏:
defaultStatus; status
。 - 窗口位置 - IE:
screenLeft; screenTop;
。 - 窗口位置 - !IE:
screenX; screenY; pageXOffset; pageYOffset;
。 - 窗口位置 - FF:
innerHeight; innerWidth; outerHeight; outerWidth;
。 - 其它:
opener; close; name; self;
。
- 状态栏:
- navigator 对象:
- DOM 文档对象模型:W3C 标准。根节点是
window.document
。- 获取节点:
- document:
getElementById; getElementsByName; getElementsByTagName;
。 - 节点指针:
firstChild; lastChild; childNodes; previousSibling; nextSibling; parentNode;
。
- document:
- 节点操作:
- 创建节点:
createElement; createAttribute; createTextNode;
。 - 插入节点:
appendChild; insertBefore;
。 - 替换节点:
replaceChild;
。 - 复制节点:
cloneNode;
。 - 删除节点:
removeChild;
。
- 创建节点:
- 属性操作(获取/设置/删除):
getAttribute; setAttribute; removeAttribute
。 - 文本操作:
insertData; appendData, deleteData, replaceData; spliceData; substring;
。
- 获取节点:
如何理解 DOM Lever?§
- DOM 一级
- DOM 二级
- DOM 三级
如何理解事件流/冒泡/捕获/委托?§
事件流:
-
事件流被分为三个阶段(15)捕获过程、(56)目标过程、(6~10)冒泡过程。
-
IE 提出的是冒泡流,而网景提出的是捕获流,后来在 W3C 组织的统一之下,JS 支持了冒泡流和捕获流,但是目前低版本的 IE 浏览器还是只能支持冒泡流(IE6, IE7, IE8 均只支持冒泡流),所以为了能够兼容更多的浏览器,建议大家使用冒泡流。
-
从事件传播的过程能够看出来,当点击鼠标后,会先发生事件的捕获
- 捕获阶段:首先 window 会获捕获到事件,之后 document、documentElement、body 会捕获到,再之后就是在 body 中 DOM 元素一层一层的捕获到事件,有 wrapDiv、innerP。 *目标阶段:真正点击的元素textSpan的事件发生了两次,因为在上面的JavaScript代码中,textSapn既在捕获阶段绑定了事件,又在冒泡阶段绑定了事件,所以发生了两次。但是这里有一点是需要注意,在目标阶段并不一定先发生在捕获阶段所绑定的事件,而是先绑定的事件发生,一会会解释一下。
- 冒泡阶段:会和捕获阶段相反的步骤将事件一步一步的冒泡到window
JavaScript 事件冒泡:
- 当触发子元素时,事件会沿着 DOM 向上冒泡。事件冒泡是实现事件委托的原理。阻止冒泡示例:
var btn = document.getElementById('btn')
btn.addEventListener('click', function (event) {
// event.preventDefault() // 阻止默认行为
event.stopPropagation() // 阻止冒泡
console.log('clicked')
})
JavaScript 事件委托(事件代理):
事件委托是将事件监听器添加到父元素,而不是每个子元素单独设置事件监听器。当触发子元素时,事件会冒泡到父元素,监听器就会触发,这种技术的好处如下。
- 优点:
- 内存占用减少,因为只需要一个父元素的事件处理程序,而不必为每个后代都添加事件处理程序。
- 无需从已删除的元素中解绑处理程序,也不许将处理程序绑定到新元素上。
- 局限性:
- focus、blur 之类的事件本身没有事件冒泡机制,所以无法委托
- mousemove、mouseout 这样的事件,虽然有事件冒泡,但是只能不断通过位置去计算定位,对性能消耗高,不适 合事件委托
示例目标:为 div 下的每个 a 标签绑定点击事件:
<div id="div1">
<a href="#" id="a1">a1</a>
<a href="#">a2</a>
<a href="#">a3</a>
<a href="#">a4</a>
</div>
<button>点击增加一个 a 标签</button>
示例原理:监听 div 下的事件触发点是不是 a 标签:
function bindEvent(elem, type, selector, fn) {
// 这样可以实现重载
if (fn == null) {
fn = selector
selector = null
}
// 绑定事件
elem.addEventListener(type, function (e) {
var target
// 有 selector 说明需要做事件代理
if (selector) {
// 获取触发事件的元素,即 e.target
target = e.target
// 看是否符合 selector 这个条件
if (target.matches(selector)) {
fn.call(target, e)
}
} else {
// 无 selector,说明不需要事件代理
fn(e)
}
})
}
使用示例:
// 使用代理 bindEvent 多一个 'a' 参数
var div = document.getElementById('div')
bindEvent(div1, 'click', 'a', function (e) {
console.log(this.innerHTML)
})
// 不使用代理
var a1 = document.getElementById('a1')
bindEvent(div, 'click', function (e) {
console.log(a1.innerHTML)
})
DOM 的事件模型?§
- DOM之事件模型分脚本模型、内联模型(同类一个,后者覆盖)、动态绑定(同类多个)
- 事件就是文档或浏览器窗口中发生的一些特定的交互瞬间,而事件流(又叫事件传播)描述的是从⻚面中接收事件的顺序。
- 事件流:
- 事件就是文档或浏览器窗口中发生的一些特定的交互瞬间,而事件流(又叫事件传播)描述的是从⻚面中接收事件的顺 序。
- 事件冒泡:即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到 较为不具体的节点。
- 事件捕获:事件捕获的思想是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。事件捕获的用意在于在。事件到达预定目标之前就捕获它。
- 事件流又称为事件传播,DOM2级事件规定的事件流包括三个阶段:
- 事件捕获阶段(capture phase)
- 处于目标阶段 (target phase)
- 事件冒泡阶段(bubbling phase)
<body>
<!--行内绑定:脚本模型-->
<button onclick="javascrpt:alert('Hello')">Hello1</button> <!--内联模型-->
<button onclick="showHello()">Hello2</button> <!--动态绑定-->
<button id="btn3">Hello3</button>
</body>
<script>
/*DOM0:同一个元素,同类事件只能添加一个,如果添加多个,
* 后面添加的会覆盖之前添加的*/
function shoeHello() {
alert("Hello");
}
var btn3 = document.getElementById("btn3");
btn3.onclick = function () {
alert("Hello");
}
/*DOM2:可以给同一个元素添加多个同类事件*/ btn3.addEventListener("click",function () { alert("hello1");
});
btn3.addEventListener("click",function () { alert("hello2");
})
if (btn3.attachEvent){
/*IE*/
btn3.attachEvent("onclick",function () {
alert("IE Hello1");
})
}else {
/*W3C*/
btn3.addEventListener("click",function () {
alert("W3C Hello");
})
}
</script>
DOM 的实现机制?§
- 当初始的 HTML 文档完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像和子框架的完成加载。
- window 的 load 事件仅在 DOM 和所有相关资源全部完成加载后才会触发。
DOM 树的构建过程?§
- 转码: 浏览器将接收到的二进制数据按照指定编码格式转化为HTML字符串
- 生成Tokens: 之后开始parser,浏览器会将HTML字符串解析成Tokens
- 构建Nodes: 对Node添加特定的属性,通过指针确定 Node 的父、子、兄弟关系和所属 treeScope
- 生成DOM Tree: 通过node包含的指针确定的关系构建出DOM Tree