BOM
BOM
BOM(Browser Object Model) 浏览器对象模型
浏览器对象模型提供了独立于内容的、可以与浏览器窗口进行互动的对象结构。
BOM 由多个对象组成,其中代表浏览器窗口的 Window 对象是 BOM 的顶层对象,其他对象都是该对象的子对象。
我们在浏览器中的一些操作都可以使用BOM的方式进行编程处理,比如:刷新浏览器、后退、前进、在浏览器中输入URL等。
是使用 JavaScript 开发 Web 应用程序的核心。
是实现 Web 开发与浏览器之间互相操作的基础。
BOM 比 DOM 更大,它包含 DOM。
window 对象
BOM 的核心对象,有两个身份:ES中的全局作用域和浏览器窗口的JavaScript接口。
-
global 全局作用域
通过var声明的所有变量都会变成window对象的属性和方法
当调用 window 下的属性和方法时,可以省略 window。
使用
window.attr
声明的变量和var
声明的变量有个区别,使用var
声明的变量,不能使用delete
删除,使用window.
声明的变量可以被删除在JavaScript中,尝试使用未声明的变量会抛出错误,但是通过
window
对象查询未声明的变量,只会返回undefined
-
窗口关系
window
对象的top
属性始终指向最外层的窗口,及浏览器窗口本身。window 对象的
parent
属性始终指向当前窗口的父窗口,如果当前窗口就是最外层窗口,则top
等于parent
window
对象的self
属性始终指向自身。 -
窗口属性
window.screenLeft // 窗口相对于屏幕左侧的距离, number (单位 px) window.screenTop // 窗口相对于屏幕顶部的距离, number (单位 px) window.innerWidth,// 获取整个浏览器【能显示内容】的宽 window.innerHeight,// 获取整个浏览器【能显示内容】的高 window.pageXOffset,// 获取浏览器【往左】滚出去的距离 window.pageYOffset,// 获取浏览器【往上】滚出去的距离 window.moveTo(x, y) // 移动到 (x, y) 坐标对应的新位置 window.moveBy(x, y) // 相对当前位置在两个方向上分别移动 x/y 个像素的距离
-
浏览器窗口大小不好确认,但是可以用
document.documentElement.clientWidth
和document.documentElement.clientHeight
来确认可视窗口的大小。移动浏览器中上面的两个属性返回的通常是实际渲染的页面的大小,而可视窗口可能只能显示一部分内容。
-
调整窗口大小可以使用
resizeTo()
和resizeBy()
两个方法。
// 缩放到 100×100 window.resizeTo(100, 100); // 缩放到 200×150 window.resizeBy(100, 50); // 缩放到 300×300 window.resizeTo(300, 300);
-
-
视口位置
浏览器窗口尺寸通常无法满足完整显示整个页面,为此用户可以通过滚动在有限的视口中查看文档。
度量文档相对于视口滚动距离的属性有两对,返回相等的值:
window.pageXoffset/window.scrollX
和 window.pageYoffset/window.scrollY
。
可以使用 scroll()
、scrollTo()
和 scrollBy()
方法滚动页面。
// 相对于当前视口向下滚动 100 像素
window.scrollBy(0, 100);
// 相对于当前视口向右滚动 40 像素
window.scrollBy(40, 0);
// 滚动到页面左上角
window.scrollTo(0, 0);
这几个方法也都接收一个 ScrollToOptions
字典,除了提供偏移值,还可以通过 behavior
属性告诉浏览器是否平滑滚动。
// 正常滚动
window.scrollTo({
left: 100,
top: 100,
behavior: 'auto'
});
// 平滑滚动
window.scrollTo({
left: 100,
top: 100,
behavior: 'smooth'
});
setTimeout()/setInterval()
- setTimeout():用于指定一段时间后执行某些代码
clearTimeout(): 清除定时器
- setInterval():每隔一段时间执行某些代码
clearInterval(): 清除定时任务
所有setTimeout()任务都会在全局作用域中的一个匿名函数中执行,因此函数中所有的 this 指向都是
window
(严格模式下是undefined
) 。如果定义setTimeout
的时候传入的是一个箭头函数,则会保留原来的 this 指向。
setTimeout
可以不记录超时ID,因为它会在满足条件(执行定义时传入的函数时)自动停止,再次定义时会重新定义一个超时任务。
清除定时器的问题
问题 1
将定时器的开始和停止过程书写在不同的事件函数内部,容易出现用户错误点击情况
1、多次点击开始,会造成加速
2、多次点击开始,不能够再停止
解决方法
每次开启新定时器之前,都清除一次前面的定时器
问题 2
需求:要求元素走到指定位置停止,例如让元素停止在 500px 的位置.
问题:如果步长设置的不合理,停止的位置可能不是正好在 500 处。
解决方法
在定时器内部每次都要判断是否走到了终点,要不要停止定时器
如果走到或超过了终点,强行拉到钟点,并停止定时器
问题 3
需求:在规定时间内让元素走到规定的结束位置,时间间隔可以更改
例如:让元素在 2 秒钟内,left 属性从 0 走到 500px.
解决方法
总距离 = 步长 * 次数;
时间间隔自定义,总时长固定
求出总次数 = 总时间 / 时间间隔
定义计数器变量,每执行一次定时器函数增加计数 1,直到执行达到总次数,停止定时器
每个setTimeout产生的任务会直接push到任务队列中;
而setInterval在每次把任务push到任务队列前,都要进行一下判断(看上次的任务是否仍在队列中)。如果还在队列中,则会被跳过。
所以建议少用setInterval(),可以用setIimeout()代替。
用setTimeout模拟setInterval
setTimeout(function () {
// 任务
setTimeout(arguments.callee, interval);
// arguments.callee()获取当前函数的引用
}, interval)
// 在前一个定时器执行完前,不会向队列插入新的定时器
// 保证定时器间隔
### 系统对话框 |
---|
1. alert() |
2. confirm() |
3. prompt() |
## location 对象 |
### 常用属性 |
假设当前加载的url是'https://juejin.cn/?sort=three_days_hottest#abc; |
### 操作地址 |
修改浏览器地址可以通过四种方式来修改: |
- assign()打开页面会立即跳转,同时在浏览器历史记录中增加一条记录 |
- replace() 打开页面跳转 记录不会被添加,浏览器后退按钮无法使用状态 |
- location.href = newLocation |
- window.location = newLocation |
- 其中 location.href 和 window.location 都会在内部显式调用 location.assign() 方法。 |
reload() |
- location.reload(); //重新加载 不一定从服务器加载 |
location.reload(true); //重新加载 从服务器加载 |
#### 历史状态管理 |
1. hashchange 事件:页面 URL 的散列变化时被触发 |
2. history.pushState() 方法:接收 3 个参数:一个 state 对象、一个新状态的标题和一个(可选的)相对 URL |
3. popstate 事件(在 window 对象上):后退时触发 |
4. history.state 属性:当前的历史记录状态 |
5. history.replaceState()方法:接收与 pushState() 一样的前两个参数 来更新状态 |
## navigator 对象 |
- 由于历史原因,Navigator已经不能识别浏览器了 |
- 一般只是用userAgent(用户代理)来判断浏览器信息 |
```javascript |
var ua = navigator.userAgent; |
if(/firefox/i.test(ua)){ |
}else if(/Chrome/i.test(ua)){ |
}else if(/msie/i.test(ua)){ |
}else if("ActiveXObject" in window){ |
} |
``` |
## screen 对象 |
- 这个对象保存的是客户端显示器等一些信息。每个浏览器都会在screen对象上暴露不同的属性 |
## history 对象 |
保存了浏览器的一些历史 相关信息的对象,本质上也是一个对象,有自己的属性和方法 |
### 导航(方法) |
1. history.go() |
- +n 为前进n页 类似浏览器的向前按钮 |
- -n 为后退n页 类似浏览器的向后按钮 |
2. history.back() |
- 前一个 |
3. history.forward() |
- 下一个 |
### hash & history |
hash |
即地址栏 URL 中的 # 符号 hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。 |
history |
利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法 它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求。 |
通过history api,我们丢掉了丑陋的#,但是它也有个问题:不怕前进,不怕后退,就怕刷新,f5,(如果后端没有准备的话),因为刷新是实实在在地去请求服务器的。 |
在hash模式下,前端路由修改的是#中的信息,而浏览器请求时不会将 # 后面的数据发送到后台,所以没有问题。 |
但是在history下,你可以自由的修改path,当刷新时,如果服务器中没有相应的响应或者资源,则会刷新出来404页面。 |
## 加载事件 |
onload 事件 |
可以给 window 对象等元素添加 onload 加载事件, |
表示只有绑定事件的元素加载完毕才能触发事件,才能执行事件函数。 |
DOMContentLoaded 事件 |
触发时,仅当DOM加载完成,不包括样式表,图片,flash等等。(IE9以上才支持) |
- 如果页面的图片很多的话, 从用户访问到onload触发可能需要较长的时间, 交互效果就不能实现,必然影响用户的体验,此时用 DOMContentLoaded 事件比较合适。 |
beforeunload :页面关闭之前执行的事件 |
unload:页面关闭时执行的事件,可以保存用户信息 |
window 对象加载完毕: |
指的是所有HTML结构加载完,并且外部引入资源(js、css、img、 视频)也加载完毕。 |
## Cookie |
Cookie是计算机上存储在小文本文件中的数据。 |
当Web服务器将网页发送到浏览器时,连接将关闭,服务器将忘记用户的所有内容。 |
发明Cookie是为了解决“如何记住用户信息”的问题. |
当用户访问网页时,他/她的名字可以存储在cookie中。 |
下次用户访问该页面时,cookie会“记住”他/她的名字。 Cookie以键值对形式保存. |
当浏览器从服务器请求网页时,属于该页面的cookie将添加到请求中。 |
这样,服务器获取必要的数据以“记住”有关用户的信息。 |
使用JavaScript创建Cookie
JavaScript可以使用document.cookie属性创建,读取和删除cookie。使用JavaScript,可以像这样创建一个cookie:
document.cookie = "username=lee";
还可以添加到期日期(以UTC时间为单位)。默认情况下,在浏览器关闭时删除cookie:
document.cookie = "username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 UTC";
使用path参数,您可以告诉浏览器cookie属于哪个路径。默认情况下,cookie属于当前页面。
document.cookie = "username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 UTC; path=/";
使用JavaScript读取Cookie
var x = document.cookie;
// 返回一个字符串中的所有cookie
使用JavaScript更改Cookie
// 可以像创建cookie一样更改cookie:旧cookie被覆盖。
document.cookie = "username=John Smith; expires=Thu, 18 Dec 2013 12:00:00 UTC; path=/";
使用JavaScript删除Cookie
删除cookie时,不必指定cookie值。只需将expires参数设置为传递日期:
document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
// 应该定义cookie路径以确保删除正确的cookie。如果未指定路径,某些浏览器将不允许您删除cookie。
Cookie字符串
document.cookie属性看起来像普通的文本字符串。但事实并非如此。
即使你将一个完整的cookie字符串写入document.cookie,当你再次读出它时,你只能看到它的名称 - 值对。
如果您设置了新cookie,则不会覆盖较旧的cookie。
新的cookie被添加到document.cookie,所以如果你再次阅读document.cookie,你会得到类似的东西:
cookie1 = value; cookie2 = value;
如果要查找一个指定cookie的值,则必须编写一个JavaScript函数来搜索cookie字符串中的cookie值。
JavaScript Cookie示例
创建一个存储访客姓名的cookie
访问者第一次到达网页时,将要求他/她填写他/她的姓名。然后将名称存储在cookie中。
下次访问者到达同一页面时,他/她将收到欢迎信息。
在这个例子中,我们将创建3个JavaScript函数:
- 用于设置cookie值的函数
- 获取cookie值的函数
- 用于检查cookie值的函数
- 设置Cookie的功能
// cookie到期之前的天数(exdays)
function setCookie(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
var expires = "expires="+ d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}
function getCookie(cname) {
var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var ca = decodedCookie.split(';');
for(var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring();
}
}
return "";
}
function checkCookie() {
var username = getCookie("username");
if (username != "") {
alert("Welcome again " + username);
} else {
username = prompt("Please enter your name:", "");
if (username != "" && username != null) {
setCookie("username", username, 365);
}
}
}
// checkCookie()在页面加载时运行该函数。
浏览器本地存储
本地存储、浏览器存储、浏览器缓存,都是一个意思,都是只讲数据存储在浏览器本地。
localStorage、sessionStorage和cookie
LocalStorage
Application -> localStorage
localStorage.setItem(key,value)
提交设置、修改存储数据,参数1是属性名,参数2是属性值
localStorage.setItem(key)
获取存储的数据,只有一个参数,即属性名,得到结果是属性值
localStorage.removeItem(key)
删除存储的数据,只有一个参数,即通过属性名,一个一个删除整条数据
localStorage.clear()
清除存储的数据,没有参数,调用后立即清空所有存储的数据
SessionStorage
Application -> sessionStorage
sessionStorage.setItem(key,value)
提交设置、修改存储数据,参数1是属性名,参数2是属性值
sessionStorage.setItem(key)
获取存储的数据,只有一个参数,即属性名,得到结果是属性值
sessionStorage.removeItem(key)
删除存储的数据,只有一个参数,即通过属性名,一个一个删除整条数据
sessionStorage.clear()
清除存储的数据,没有参数,调用后立即清空所有存储的数据
localStorage和sessionStorage的异同点
相同点:
都是按域名保存起来的,如果多个网页,保存在同一个域名内,那网页之间,可以访问这些数据;
但不同域名内的网页,不能访问
保存数据默认都是字符串
的形式,所以,默认取出来的也是字符串
因此,如果要保存非字符串的数据,可以先把数据用JSON.stringify转换成JSON字符串,然后进行保存
取出时,再用JSON.parse转成JS相应的数据
不同点:
localStorage:只要不手动删除,会永久保存
sessionStorage:只要关闭当前的网页,存储的内容就会被清空,因此也可以叫临时存储
或会话存储