DOM事件流 & BOM对象

166 阅读6分钟

今天我们讨论两个与浏览器相关的对象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的事件传播分为三个阶段

  1. 捕获阶段:事件对象通过目标的祖先从窗口传播到目标的父对象。这个阶段称为捕获阶段。
  2. 目标阶段:事件对象到达触发事件对象的目标。这个阶段也被称为目标阶段。如果事件类型没有事件冒泡,则事件对象将在完成此阶段后停止。
  3. 冒泡阶段:事件对象以相反的顺序通过目标依次向祖先进行传播,从目标的父对象开始,到窗口结束。这个阶段也称为冒泡阶段。

事件在整个事件流的传播过程中有两个属性需要注意

  • currentTarget:在整个事件流是变化的,表示事件到达的目标元素
  • target:在整个事件流是不变的,表示触发事件的元素

事件委托

事件的委托利用事件冒泡的原理,把子元素的事件响应处理函数委托至父元素处理。其优点如下

  1. 减少事件的绑定,减少占用内存,减少dom的引用
  2. 新增的子元素可以动态的添加绑定事件

如下代码

<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执向同一个对象: image.png 最长用的是解析URL信息,假设当前窗口加载的URL是 www.lius.com:8080/article?id=…

属性说明
location.hash"#contents"URL 散列值,#号后面,表示一个DOMString,如果没有这显示空
location.hostwww.lius.com:8080服务器名(域名)以及端口号
location.port8080端口号
location.hostnamewww.lius.com服务器名(域名)
location.herfwww.lius.com:8080/article?id=…完整的URL地址,通过location.toString()也返回相同值
location.pathname/articleURL 中的路径
location.protocolhttps:协议
location.search?id=12URL 中的查询字符串,以?号开头
location.originwww.lius.comURL 源地址

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 没有改变