【浏览器】- BOM

312 阅读8分钟

BOM (Browser Object Model),即浏览器对象模型。BOM提供了很多接口用于操作浏览器的各种功能,这些功能与任何网页内容无关,所以说BOM的主要用途就是操作浏览器

Window

window 对象是 BOM 提供的通过 JavaScript 访问浏览器窗口的一个接口,也是 ECMAScript 规定的 Global 对象(全局对象)。

在全局作用域下,当使用var声明变量时,变量会自动挂载到window对象下;而使用letconst声明的变量则不会自动挂载到window下:

const a = 1
console.log(window.a) // undefined
var b = 2
console.log(window.b) // 2

另外,使用function声明的函数变量,还是会挂载到window

function c(){ return false }
console.log(window.c) // ƒ c(){return false}

窗口关系

在存在 <iframe>嵌套的网页上,我们可能会需要判断窗口之间的关系,BOM 提供了以下几个属性来表示窗口关系:

  • window.parent表示当前窗口的父窗口
  • window.top表示最外层窗口
  • window.self表示 window对象本身

窗口位置

  • window.screenLeftwindow.screenTop 用于表示浏览器窗口相对于屏幕左侧和顶部的位置 ,返回值的单位是CSS像素。
  • window.moveTo()window.moveBy()方法可以移动窗口至指定的位置

窗口大小

  • outerWidthouterHeight返回浏览器窗口自身的大小(不管是在最外层 window 上使用,还是在 iframe 中使用)
  • innerWidthinnerHeight返回浏览器窗口中页面可视区域的大小(不包含浏览器边框和工具栏)
  • window.resizeTo()window.resizeBy()方法可以调整窗口大小,resizeTo()接收新的宽度和高度值,而resizeBy()接收宽度和高度各要缩放多少

调整窗口位置和大小的方法,大多数浏览器默认都是禁用的,实测 Chrome 中控制台中直接调用没有任何响应。

视口位置

先解释下“视口”的意思,视口即 view-port,指的是浏览器的可视区域,说白了就是整个浏览器页面(不包括工具栏和底栏),因为网页上的内容常常很多,导致我们需要滚动页面来查看内容,滚动网页就相当于滚动视口。

window.scrollTo()window.scrollBy()方法可以使视口滚动,例如:

// 接受2个参数,分别是X-水平距离和Y-垂直距离
// 相对于当前视口向下滚动100像素
window.scrollBy(0, 100);

// 滚动到页面左上角
window.scrollTo(0, 0);

也可以传入一个配置对象来实现平滑滚动:

window.scrollTo({
  left: 100,
  top: 100,
  behavior: 'smooth' // 有 auto 和 smooth 两个可选值
});

上面的方法没有被禁用,可以很方便的调用。

窗口导航

window.open()方法可以用于导航到指定 URL,也可以用于打开新浏览器窗口,它会创建一个新的浏览器窗口对象,与右键菜单中的新建窗口选项作用相同。

这个方法接收3个参数:

  • url:要跳转的目标链接地址
  • strWindowName :新窗口的名称(并不是新窗口的浏览器tab的标题),可以用来作为 <a><form> 的目标属性值,不能含有空白字符
  • strWindowFeatures:一个字符串,列出了将要打开的窗口的一些特性(窗口大小、位置、是否显示菜单栏等等) ,字符串中不能包含任何空白字符,特性之间用逗号分隔开。
window.open("http://www.bing.com/",
            "bingWindow",
            "height=400,width=400,top=10,left=10,resizable=yes");

window.open的返回值是新建窗口的引用,如果新建的窗口与当前窗口满足同源策略,那么就可以访问到其中的属性或方法。

定时器

  • setTimeout(callback, time),在等待 time毫秒数之后执行回调函数 callback,通过 clearTimeout来清除定时器
  • setInterval(callback, time),每隔 time毫秒数就执行回调函数 callback,通过 clearInterval来清除定时器

使用setTimeout是设置循环任务的推荐做法。setInterval()在实践中很少会在生产环境下使用,因为一个任务结束和下一个任务开始之间的时间间隔是无法保证的,有些循环定时任务可能会因此而被跳过。一般来说,最好不要使用setInterval,而是使用 setTimeout替换实现。

Navigator

window.navigator 用于查询浏览器的相关信息。它最常用的用途是返回当前浏览器的用户代理(user agent)字符串。通过在浏览器的移动端设备模拟中切换设备类型,可以看到不同的 user agent (UA)navigator.userAgent 可以获取访问当前的设备类型信息,主要有以下用途:

  • 统计用户浏览器使用情况。通过判断每个 IP 的 UA 来确定这个IP是用什么浏览器访问的,以得到使用量的数据
  • 根据用户使用浏览器的不同,显示不同的排版从而为用户提供更好的体验。有些网站会根据这个来调整打开网站的类型,如果是移动设备就打开wap 页面,显示非手机的就打开 pc 常规页面

Screen

window.screen 在实际开发中用的比较少,不过了解一下还是可以的,它保存的纯粹浏览器窗口外面的客户端显示器的信息,比如像素宽度和像素高度:

  • availWidth:返回窗口中水平方向可用空间的像素值
  • colorDepth:返回屏幕的色彩深度
  • height:以像素为单位返回屏幕的高度
  • orientation:返回当前屏幕的转向

Location

window.location 是最有用的 BOM 对象之一,提供了当前窗口中加载文档的信息,以及通常的导航功能。它既是 window 的属性,也是 document 的属性,window.locationdocument.location 指向同一个对象。

属性

image.png

修改地址

要修改现有的页面地址有很多方法,常用的包括下面的几种方式:

  • location.assign(url) 传入一个 url 链接之后,导航到新 URL 的页面,同时在浏览器历史记录中增加一条
  • window.location & location.href 直接将 url 赋值给 location 或者 location.href 也能实现页面跳转
  • location.hash 指定 location.hash 的值也可以改变当面页面 url 连接中 # 号部分之后的内容,常用于实现局部页面的切换
  • location.replace(url) 前面几种方式修改页面 url 之后会体现在浏览器历史记录中,这样页面 url 修改后还可以回退到之前的页面;而使用 replace 跳转页面以后,将不会在历史记录中保存,它会替换当前 url 而不是新建,所以也就不能回退
  • location.reload(flag) reload 可以重新加载当前页面,参数 flag 是一个布尔值,不传参数或者传入false ,浏览器会自己做出判断是否从缓存中加载页面;如果为 true,则强制浏览器从服务器重新请求页面

锚点定位

如果需要滚动到页面指定位置,可以通过给元素添加锚点,然后通过指定 href 来实现,例如现在要滚动到页面的第 22 个段落处 <p id="p22">这是需要滚动的目标位置</p>,可以这样:

// 第一种方法: # 表示锚点,后面接 id 的值
location.href = "#p22"

// 第二种方法:可以通过 a 标签
<a href="#p22"></a>

跳转到锚点位置以后,浏览器地址栏中的 URL 最后面会加上 #p22

URL 查询参数解析

URLSearchParams 提供了一组标准 API 方法,通过它们可以检查和修改查询字符串。给 URLSearchParams 构造函数传入一个查询字符串,就可以创建一个实例。这个实例提供了get()、set()、delete()方法,可以对查询字符串执行相应操作

let queryStr = "http://www.bing.com?q=javascript&num=10";
let searchParams = new URLSearchParams(queryStr);

// 获取 URL 中的查询参数字符串
searchParams.toString();  // "q=javascript&num=10"

// 检测是否存在某个参数
searchParams.has("num");         // true

// 获取某个参数的值
searchParams.get("num");         // 10

// 设置某个参数的值
searchParams.set("page", "3");
searchParams.toString();  // "http://www.bing.com?q=javascript&num=10&page=3"

// 删除某个参数
searchParams.delete("q");
searchParams.toString();  // "http://www.bing.com?num=10&page=3"

History

window.history 对象表示当前窗口首次使用以来用户的导航历史记录,出于安全考虑,这个对象不会暴露用户访问过的 URL。通过 history 可以实现在不刷新页面的前提下动态改变浏览器地址栏中的URL地址,从而动态修改页面上所显示的资源。

导航

  • history.go() 可以在用户历史记录中沿任何方向导航,可以前进也可以后退。这个方法只接收一个参数,表示前进或后退多少步。负值表示在历史记录中后退(类似点击浏览器的“后退”按钮),而正值表示在历史记录中前进(类似点击浏览器的“前进”按钮)
// 后退一页
history.go(-1);

// 前进一页
history.go(1);

// 前进两页
history.go(2);
  • history.back() & history.forward() 是 go 方法的两个特例,back() 可以在历史记录中后退 1 步,相当于 go(-1);forward() 可以前进 1 一步,相当于 go(1)
  • history.length 这个属性可以返回当前页面(即当前这个浏览器标签页内)总共产生的历史记录的条数

历史状态管理

  • hashchange 事件监听函数,在当前页面的 URL 发生改变时会被触发
  • popstate 事件监听,历史记录发生改变时触发,调用history.pushState()或者history.replaceState()不会触发popstate事件
  • history.pushState(state, title, url) 添加一条历史记录,但不刷新页面(不会触发 hashchange 事件,但会触发 popstate事件)。
    • 参数 state 是一个对象,用于指定网址相关的状态对象。
    • 参数 title 指定新页面的标题,但是所有浏览器目前都忽略这个值,因此这里可以填 null
    • 参数 url 用于指定新历史记录条目的 URL,必须与当前页面同源,否则会报错。
  • history.replaceState()pushState() 唯一的不同在于,pushState() 会创建新的历史记录,而replaceState()只会替换当前的历史记录,同样也不会触发 hashchange 事件