JS学习笔记(十一)BOM
一、window对象
BOM的核心是window对象,表示浏览器实例。window对象在浏览器中的两重身份:
- ES中的 Global 对象
- 浏览器窗口的 JS 接口
1.1 窗口关系
-
top 对象:始终指向最上层(最外层)的窗口,即浏览器本身。
-
parent 对象:始终指向当前窗口的父窗口。若当前窗口是最上层窗口,则parent等于window
-
self 对象:终极window属性,始终指向window。self 和 window 就是同一个对象。
最上层的window若不是通过window.open()打开的,那其name属性就不会包含值。
1.2 窗口位置与像素比
1.2.1 moveTo() 和moveBy()
window对象的位置可以头盖骨不同的属性和方法来确定。现代浏览器提供了 screenLeft 和 screenTop 属性,用于表示窗口相对于屏幕左侧和顶部的位置,返回值的单位是CSS像素。可以使用moveTo() 和moveBy() 方法移动窗口。接收两个参数
- moveTo():接收要移动到新位置的绝对坐标x和y
- moveBy():接收相对当前位置在两个方向上移动的像素数
1.2.2 像素比
物理像素与CSS像素之间的转换比例,由window.devicePixelRatio属性提供。window.devicePixelRatio与每英寸像素数(DPI,dots per inch)对应。DPI表示像素密度,而window.devicePixelRatio表示物理像素与逻辑像素之间的缩放系数。
1.3 窗口大小
1.3.1 innerWidth、innerHeight、outerWidth、outerHeight
浏览器支持:innerWidth、innerHeight、outerWidth、outerHeight。
- outerWidth、outerHeight:返回浏览器窗口自身的大小
- innerWidth、innerHeight:返回浏览器窗口页面视口的大小(不包括浏览器边框和工具栏)
浏览器窗口自身的精确尺寸不好确定,但可以缺点页面的视口大小
let pageWidth = window.innerWidth;
let pageHeight = window.innerHeight;
if (typeof pageWidth!="number") {
if(document.compatMode == 'CSS1Compat') { //检查页面是否处于标准模式
pageWidth = document.documentElement.clientWidth;
pageHeight = document.documentElement.clientHeight;
}else {
pageWidth = document.body.clientWidth;
pageHeight = document.body.clientHeight;
}
}
CSS1Compat 对应strict mode ,标准兼容模式开启
- 移动设备上:window.innerWidth和 window.innerHeight返回视口的大小,但document.documentElement.clientWidth 和 document.documentElement.clientHeight中提供了相同的信息。在缩放页面时,这些值也会变化。
- **其他移动浏览器上:**document.documentElement.clientWidth 和 document.documentElement返回布局视口的大小,即渲染页面的大小。布局视口的信息 保存在document.body.clientWidth和document.body.clientHeight中
1.3.2 resizeTo() 和resizeBy()
使用 resizeTo() 和 resizeBy()方法调整窗口大小
- resizeTo():接收新的宽度和高度
- resizeBy():接收宽度和高度各要缩放多少
1.4 视口位置
浏览器窗口尺寸通常无法满足完整显示整个页面,为此用户可以通过滚动在有限的视口中查看文档。度量文档相对于视口滚动距离的属性有两对,返回相等的值**:window.pageXoffset/window.scrollX 和window.pageYoffset/window.scrollY**
可以使用**scroll()、scrollTo()、scrollBy()**方法滚动页面,3个方法都接收表示相对视口距离的x和y坐标,这两个参数在前面两个方法中表示要滚动到的坐标,在最后一个方法中表示滚动的距离。这三个方法也接收一个ScrollToOptions字典,除了提供偏移值,还可通过behavior属性告诉浏览器是否平滑滚动
//正常滚动
window.scrollTo({
left:100,
top:100,
behavior:'auto'
});
//平滑滚动
window.scrollTo({
left:100,
top:100,
behavior:'smooth'
});
1.5 导航与打开新窗口
window.open()用于导航到指定的URL,也可用于打开新浏览器窗口。这个方法接收4个参数:要加载的URL、目标窗口、特性字符串和表示新窗口在浏览器历史记录中是否替代但其那加载页面的布尔值
若window.open()第二个参数时一个已经存在的窗口或窗格的名字,则会在对应的窗口或窗格中打开URL
window.open("http://www.wrox.com/","topFrame");
如果有一个窗口名叫“topFrame”,则这个窗口就会打开这个URL,否则就会打开一个新窗口并将其命名为“topFrame”。第二个参数也可以是特殊的窗口名:_self
,_parent
,_top
,_blank
1.5.1 弹出窗口
window.open()的第三个参数,即特性字符串,用于指定新窗口的配置。若没有传第三个参数,则新窗口会带有所有默认的浏览器特性(工具栏、地址栏、状态栏等)。特性字符串是一个逗号分隔的设置字符串,用于指定新窗口包含的特性
设置 | 值 | 说明 |
---|---|---|
fullscreen | “yes"or"no” | 表示新窗口是否最大化。仅限IE支持 |
height | 数值 | 新窗口高度,不能小于100 |
width | 数值 | 新窗口宽度,不能小于100 |
top | 数值 | 新窗口的x轴坐标,不能为负值 |
left | 数值 | 新窗口的y轴坐标,不能为负值 |
location | “yes"or"no” | 表示是否显示地址栏 |
Menubar | “yes"or"no” | 表示是否显示菜单栏,默认为no |
resizable | “yes"or"no” | 表示是否可以拖动改变新窗口的大小,默认为no |
scrollbars | “yes"or"no” | 表示是否可以在内容过长时滚动,默认为no |
status | “yes"or"no” | 表示是否显示状态栏 |
toolbar | “yes"or"no” | 表示是否显示工具栏,默认为no |
window.open("http://www.wrox.com/","wroxWindow","height=400,width=400,top=10,left= 10,resiable=yes");
新创建窗口的window对象有一个属性opener,指向打开它的窗口。 这个属性只在弹出窗口的最上层window对象有定义,是指向调用window.open()打开它的窗口或窗格的指针。把opener设置为null表示新打开的标签页不需要与打开它的标签页通信, 因此可以在独立进程中运行。连接一旦切断,就无法恢复。
虽然新建窗口中有指向打开它的窗口的指针,当窗口不会跟踪记录自己打开的新窗口
1.5.2 弹窗屏蔽程序
在浏览器扩展或其他程序屏蔽弹窗时,window.open() 通常会抛出错误。因此要准确检测弹窗是否被屏蔽,除了检测window.open()的返回值,还要把它用try/catch包装起来:
let blocked = false;
try {
let wroxWin = window.open("http://www/wrox.com","_blank");
if(wroxWin == null) {
blocked = true;
}
} catch(ex) {
blocked =true;
}
if (blocked) {
alert("The popup was blocked!")
}
1.6 定时器
JS在浏览器中时单线程执行的。
- setTimeout():用于指定在一定时间后执行某些代码
- setInterval():用于指定每隔一段时间执行某些代码
setTImeout接收两个参数:要执行的代码和在执行回调函数前等待的时间(毫秒)。JS维护了一个任务队列。其中的任务会按照添加到队列的先后顺序执行。
setTimeout()第二个参数只是告诉JS引擎在指定的毫秒数过后把任务添加到这个队列。若队列时空的,则会立即执行该代码,若不是空的,则代码必须等待前面的任务执行完才能执行。应用场景:倒计时,轮播图
调用setTimeout()时,会返回一个表示该超市排期的数值ID。这个超时ID是被排期执行代码的唯一标识符,可用于取消该任务。 调用clearTimeout()方法,必须要在指定时间到达之前调用clearTimeout(),在任务执行之后调用是没有效果的。
let timeoutId = setTimeout(() => alert("hello"),1000);
clearTimeout(timeoutId);
1.7 系统对话框
同步方法:alert()、confirm()、提示框prompt(),可以让浏览器调用系统对话框向用户显示信息。这些对话框都是同步的模态对话框,即在他们显示的时候,代码会停止执行,消失后继续执行。
prompt中,若用户单击了OK按钮,则prompt会返回文本框中的值。
let res = prompt("What is your name?", "");
if (res !== null) {
alert("welcome, " + res);
}
异步方法:find() 和 print (),控制权会立即返回给脚本
二、location 对象
location 非常有用,他提供了当前窗口中加载文档的信息,以及通常的导航功能。它既是window的属性,也是document的属性。location不仅保存着当前加载文档的信息,也保存着把URL解析为离散片段后能够通过属性访问的信息
假设url:http://foouser:barpassword@www.wrox.com:80/WileyCDA/?q=javascript&num=10#contents
属性 | 值 | 说明 |
---|---|---|
location.hash | “#contents” | URL散列值(井号后跟零个或多个字符),若没有则为空字符串 |
location.host | “www.wrox.com:80” | 服务器名及端口号 |
location.hostname | “www.wrox.com” | 服务器名 |
location.href | “http://www.wrox.com:80/WileyCDA/?q=javascript&num=10#contents” | 当前加载页面完整的URL。location的toString()返回这个值 |
location.pathname | “/WileyCDA/” | URL中的路径和文件名 |
location.port | “80” | 端口号 |
location.protocol | “http:” | 协议 |
location.search | “?q=javascript&num=10” | URL的查询字符串。该字符串以问号开头 |
location.username | “foouser” | 域名前指定的用户名 |
location.password | “barpassword” | 域名前指定的密码 |
location.origin | “http://www.wrox.com” | URL的源地址 |
2.1 查询字符串
location.search 返回了从问号开始直到URL末尾的所有内容,但没有办法逐个访问每个查询参数,下面的函数解析了查询字符串,并返回一个以每个查询参数为属性的对象:
let getQueryStringArgs = function () {
// 取得没有问号开头的查询字符串
let qs = (location.search.length > 0 ? location.search.substring(1) : "");
// 保存数据的对象
let args = {};
// 把每个参数添加到args对象
for (let item of qs.split("&").map(kv => kv.split("&"))) {
let name = decodeURIComponent(item[0]),
value = decodeURIComponent(item[1]);
if (name.length) {
args[name] = value;
}
}
return args;
}
参数名和参数值需要使用decodeURIComponent()解码是因为查询字符串通常是编码后的格式
URLSearchParams
URLSearchParams 提供了一组标准的API,通常它们可以检查和修改查询字符串。给URLSearchParams构造函数传入一个查询字符串,就可以创建一个实例。实例上暴露了get()、set()、delete()等方法
let qs ='?q=javascript&num=10';
let searchParams =new URLSearchParams(qs);
console.log(searchParams.toString());//"q=javascript&num=10"
searchParams.has("num");//true
searchParams.get("num");//10
searchParams.set("page",3);
console.log(searchParams.toString());//"q=javascript&num=10&page=3"
searchParams.delete("q");
console.log(searchParams.toString());//"num=10&page=3"
支持将URLSearchParams的实例用作可迭代对象:
for (let param of searchParams) {
console.log(param);
}
//["q","javascript"]
//["num","10"]
2.2 操作/修改地址
方法一:通过location对象修改浏览器地址
使用assign() 方法传入一个URL,若给location.href 或 window.location 设置一个URL,也会调用assign()。
修改location对象的属性也会修改当前加载的页面。其中,hash、search、hostname、pathname和port属性被设置为新值后都会修改当前URL。 除hash,只要修改location的一个属性都会导致页面重新加载新URL。若不希望增加历史记录,可以使用replace()方法。调用replace()后,用户不能回到前一页。
方法二:reload()
调用reload()而不传参,页面会以最有效的方式重新加载
location.reload();//重新加载,可能是从缓存加载
location.reload(true);//重新加载,从服务器加载
脚本中位于reload()调用之后的代码可能执行也可能不执行,取决于网络延迟和系统资源等因素。所以最好把reload()作为最后一行代码
三、navigator 对象
只要浏览器启动JS,navigator 对象就一定存在
navigator实现接口的属性和方法:
3.1 检测插件
检测浏览器是否安装了某个插件时发开中的常见需求,除了IE10及更低版本外的浏览器,都可通过plugins数组来确定。数组中每一项都包含:
- name:插件名称,包含识别插件所需的必要信息
- description:插件介绍
- filename:插件的文件名
- length:由当前插件处理的MIME类型数量
IE11的window.navigator对象开始支持plugins和mimetype属性。
let hasPlugin = function(name) {
name = name.toLowerCase();
for(let plugin of window.navigator.plugins) {
if(plugin.name.toLocaleLowerCase().indexOf(name) > -1) {
return true;
}
}
return false;
}
console.log(hasPlugin("Flash")); //检测flash
3.2 注册处理程序
现代浏览器支持navigator上的registerotocolHandler() 方法。该方法可以把一个网站注册为某种特定类型信息应用程序。 使用registerotocolHandler()必须传入三个参数:要处理的协议、处理该协议的URL、应用名称。
如:把一个Web应用程序注册为默认邮件客户端
navigator.registerProtocolHandler("mailto","http://www.somemailclient.com? cmd=%s","Some Mail Client")
四、screen对象
保存纯粹的客户端能力信息,也就是浏览器窗口外的客户端显示器信息,如:像素宽度
五、history 对象
表示当前窗口首次使用以来用户导航历史记录
5.1 导航
go()方法可以用在用户历史记录中沿任何方向导航, 可以前进也可以后退。只接收一个参数,可以是一个整数,表示前进或者后退多少步。负值表示后退。
go()方法的两个简写方式:back():后退一页 和 forward():前进一页
history还有一个属性:length,表示历史记录中有多少个条目
5.2 历史状态管理
5.2.1 hashchange
hashchange会在页面URL的散列变化时触发。状态管理API 可以让开发者改变浏览器URL而不会加载新页面。可以使用 history.pushState() 方法。接收3个参数:一个state对象、一个新状态的标题和一个可选的相对URL
let stateObj = {fpp:'bar'};
history.pushState(stateObj,"title","baz.html");
pushState()方法执行后,状态信息就会被推到历史记录中,浏览器地址栏也会改变以反映新的相对URL。
- 后退按钮对应window对象上的popState事件
- 可以通过history.state获取当前的状态对象,使用replaceState()更新状态。更新状态不会创建新的历史记录,只会覆盖当前信息。
六、BOM常用事件
6.1 页面加载事件
window.onload() = function(){} ;
或
window.addEventListener("load",function(){});
当文档内容完全加载完成会触发该事件
注意:
- 有了window.onload就可以把JS代码写到页面元素的任何地方,因为onload是等页面加载完毕再去执行处理函数
- window.onload传统注册事件方式只能写一个,有多个以最后一个为准
document.addEventListener("DOMContentLoaded",function() {})
DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等。但从用户访问到onload触发可能需要较长的时间,此时用DOMContentLoaded比较合适
6.2 调整窗口大小事件
window.onresize() = function(){} ;
或
window.addEventListener("resize",function(){});
注意:
- 只要窗口大小发生变化,就会触发该事件
- 经常利用该事件完成响应式布局