今天我们讨论两个与浏览器相关的对象DOM 和 BOM
概念
- DOM:文档对象模型(Document Object Model,简称DOM),描述了处理网页内容的方法和接口。最根本对象是document(window.document)。此处有更详细的介绍。
- BOM:浏览器对象模型(Browser Object Model),描述了与浏览器进行交互的方法和接口。由navigator、history、screen、location、window五个对象组成的,最根本对象是window。
区别:DOM描述了处理网页内容的方法和接口,BOM描述了与浏览器进行交互的方法和接口
针对于DOM的操作有很多,本篇只讨论DOM事件流
DOM 事件流
DOM的事件传播分为三个阶段
- 捕获阶段:事件对象通过目标的祖先从窗口传播到目标的父对象。这个阶段称为捕获阶段。
- 目标阶段:事件对象到达触发事件对象的目标。这个阶段也被称为目标阶段。如果事件类型没有事件冒泡,则事件对象将在完成此阶段后停止。
- 冒泡阶段:事件对象以相反的顺序通过目标依次向祖先进行传播,从目标的父对象开始,到窗口结束。这个阶段也称为冒泡阶段。
事件在整个事件流的传播过程中有两个属性需要注意
- currentTarget:在整个事件流是变化的,表示事件到达的目标元素
- target:在整个事件流是不变的,表示触发事件的元素
事件委托
事件的委托利用事件冒泡的原理,把子元素的事件响应处理函数委托至父元素处理。其优点如下
- 减少事件的绑定,减少占用内存,减少dom的引用
- 新增的子元素可以动态的添加绑定事件
如下代码
<ul id='ul'>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<ul>
<script>
// 想要在所有的 li 上面绑定事件,通过事件委托只在父元素ul上面绑定
const dom = document.getElementById("ul");
// 绑定点击事件
dom.addEventListener('click',function(e){
// 如果目标元素是li 标签
if(e.target.matches('li')){
console.log(.target.innerHtml)
}
})
</script>
阻止事件传播的相关方法
阻止事件传播的相关方法有三个,我们依次说一下
- stopPropagation
event.stopProgation() 阻止捕获和冒泡阶段中当前事件的进一步传播。 但是,它不能防止任何默认行为的发生,如果想要阻止事件的默认动作需要调用event.preventDefault()方法
- stopImmediatePropagation()
event.stopImmediatePropagation() 这个方法和stopPropagation()方法类似,都能阻止事件在事件流之间的传播。 除此之外,也阻止了该元素上同一种事件类型的其他监听方法
- preventDefault()
event.preventDefault() 如果此事件没有被显式处理,它默认的动作也不应该照常执行。 但是事件还会在事件流之间传播,除非通过event.stopPropagation()方法阻止了事件的传播 需要注意的是,可以通过event.defaultPrevented 判断是否阻止了默认事件行为 if(event.defaultPrevented){ /* 事件的默认动作已被取消 */ }
Tips:
针对于 IE8 及以下的浏览器,事件流中只有事件冒泡没有事件捕获阶段,阻止事件的冒泡需要执行 window.event.cancelBubble = true
BOM对象
ECMAScript 把浏览器对象模型(BOM)描述为JavaScript的核心,实际上BOM是通过JavaScript开发web应用的核心。BOM提供了与网页无关的浏览器功能对象:
- window:BOM 的核心
- location:获取页面信息
- navigation:标识浏览器
- history:操作浏览器历史
- ......
window 对象
window对象是BOM的核心,表示浏览器的实例,在浏览器中有两重身份,分别表示全局对象和浏览器窗口的JavaScript接口。所有通过var定义的全局变量和函数都会变成window全局对象的属性和方法。都可以使用window.xx 调用。
除此之外,window对象上面有一系列改变窗口大小,位置导航以及像素比(devicePixelRatio)等属性和方法。其中像素比是一个十分重要的内容,先不在这里讨论。后续会有一章专门叙述。
location对象
location 对象是在工作中使用最多的一个对象,他提供了当前窗口加载文档的信息,以及导航功能。还有一个独特的特性,它既是window的属性也是document的属性,也就是说window.location和document.location执向同一个对象:
最长用的是解析URL信息,假设当前窗口加载的URL是 www.lius.com:8080/article?id=…
属性 | 值 | 说明 |
---|---|---|
location.hash | "#contents" | URL 散列值,#号后面,表示一个DOMString,如果没有这显示空 |
location.host | www.lius.com:8080 | 服务器名(域名)以及端口号 |
location.port | 8080 | 端口号 |
location.hostname | www.lius.com | 服务器名(域名) |
location.herf | www.lius.com:8080/article?id=… | 完整的URL地址,通过location.toString()也返回相同值 |
location.pathname | /article | URL 中的路径 |
location.protocol | https: | 协议 |
location.search | ?id=12 | URL 中的查询字符串,以?号开头 |
location.origin | www.lius.com | URL 源地址 |
tips:还有两个属性不经常用location.username和location.password分别表示域名前指定的用户名和密码, 例如:username1:password1@www.lius.com/article?id=… 其用户名和密码分别是username1 和password1
**
- URLSearchParams
URLSearchParams 提供了一组标准API 方法,通过它们可以检查和修改查询字符串。给URLSearchParams 构造函数传入一个查询字符串,就可以创建一个实例。这个实例上暴露了get()、set()和delete()等方法,可以对查询字符串执行相应操作。如下所示:
let qs = "?id=12&page=1&pageSize=10";
let searchParams = new URLSearchParams(qs);
console.log(searchParams.toString()); // "id=12&page=1&pageSize=10"
searchParams.has("id"); // true
searchParams.get("id"); // 12
searchParams.set("page", "3");
console.log(searchParams.toString()); // "id=12&page=3&pageSize=10"
searchParams.delete("id");
console.log(searchParams.toString()); // "page=3&pageSize=10"
navigation 对象
navigator 是由Netscape Navigator 2 最早引入浏览器的,现在已经成为客户端标识浏览器的标准。只要浏览器启用JavaScript,navigator 对象就一定存在。但是与其他BOM对象一样,每个浏览器都支持自己的属性。
history 对象
history对象表示,当前窗口用户的导航记录,该对象不会向外暴露用户访问过的URL,但是可以通过方法实现前进和后退
history.go(-1);// 后退一页
history.go(1);// 前进一页
history.go(2);// 前进两页
history.back();// 后退一页
history.forward();// 前进一页
history.length // 表示已经记录了多少条目,通过该属性反应了用户的操作记录次数
HTML5 添加了新方法 pushState和replaceState,表示添加和替换历史记录的条目,语法如下
history.pushState(state, title[, url])
history.replaceState(state, title[, url])
- state: 一个于指定网址相关的状态对象,popstate事件触发时,该对象会传入回调函数中。如果不需要这个对象,此处可以填null
- title: 当前大多数浏览器都忽略此参数
- url: 新历史记录条目的URL由此参数指定,新网址必须与当前网址同源
例如,当前页面的RUL 为 www.lius.com/article?id=…
history.pushState(null,null,"https://www.lius.com")
此时页面窗口URL改变为 https://www.lius.com,但是页面并没有跳转还在当前页面,同时history.length +1
history.replaceState(null,null,"https://www.lius.com")
此时会把当前页面的URL替换为 https://www.lius.com,此时非得页面没有跳转,history.length 没有改变