目录
一、BOM概述
- 1.什么是BOM?
- DOM 就是一套操作HTML标签的API(接口/方法/属性)
- BOM 就是一套操作浏览器的API(接口/方法/属性)
- 2.BOM中常见的对象
- window:代表整个浏览器窗口
- 注意点:window是BOM中的一个对象, 并且是一个顶级的对象(全局)
- navigator:代表当前浏览器的信息, 通过 navigator 我们就能判断用户当前是什么浏览器(浏览器类型)
- location:代表浏览器地址栏的信息, 通过 location 我们就能设置或者获取当前地址信息
- history:代表浏览器的历史信息, 通过 history 来实现 刷新 / 上一步 / 下一步
- 注意点:出于隐私考虑, 我们并不能拿到用户所有的历史记录, 只能拿到当前的历史记录
- screen:代表用户的屏幕信息
- window:代表整个浏览器窗口
二、BOM对象
1.navigator
- navigator:代表当前浏览器的信息;可以通过 navigator 判断用户当前使用的是什么浏览器
// console.log(window.navigator); // userAgent: ... Chrome ...
// 1.获取浏览器信息中userAgent信息
let agent = window.navigator["userAgent"];
console.log(agent);
// /chrome/i 正则表达式,i:不区分大小写
// console.log(/chrome/i.test(agent));
// 2.利用正则表达式,判断浏览器的类型
if(/chrome/i.test(agent)){
alert("当前是谷歌浏览器");
}
else if(/firefox/i.test(agent)){
alert("当前是火狐浏览器");
}
else if(/msie/i.test(agent)) {
alert("当前是低级IE浏览器");
}
else if("ActiveXObject" in window){
alert("当前是高级IE浏览器");
}
2.location
- location:代表浏览器地址栏的信息;通过 location 我们就能 设置或者获取当前地址信息
<button id="btn1">获取</button>
<button id="btn2">设置</button>
<button id="btn3">刷新</button>
<button id="btn4">强制刷新</button>
<script>
let oBtn1 = document.querySelector("#btn1");
let oBtn2 = document.querySelector("#btn2");
let oBtn3 = document.querySelector("#btn3");
let oBtn4 = document.querySelector("#btn4");
// console.log(window.location);
oBtn1.onclick = function () {
// 获取当前url地址
console.log(window.location.href);
};
oBtn2.onclick = function () {
// 设置url地址
window.location.href = "http://it666.com";
};
oBtn3.onclick = function () {
// 刷新
window.location.reload();
};
oBtn4.onclick = function () {
// 强制刷新
window.location.reload(true);
}
</script>
3.history
- history:代表浏览器的历史信息, 通过 history 来实现 刷新 / 前进 / 后退
- window.history.go(0) # 刷新
- window.history.go(1) # 前进
- window.history.forward()
- window.history.go(-1) # 后退
- window.history.back()
- 注意点:出于隐私考虑, 我们并不能拿到用户所有的历史记录, 只能拿到当前的历史记录
<h1>我是第一个界面</h1>
<button id="btn1">前进</button>
<button id="btn2">刷新</button>
<a href="04-BOM对象-history02.html">新的界面222</a>
<script>
let oBtn1 = document.querySelector("#btn1");
let oBtn2 = document.querySelector("#btn2");
oBtn1.onclick = function () {
// 前进
// window.history.forward();
window.history.go(1);
};
// 注意点:
// 只有当前访问过其它的界面, 才能通过forward/go方法前进
// 如果给go方法传递1, 就代表前进1个界面, 传递2就代表进行2个界面
oBtn2.onclick = function () {
// 刷新
window.history.go(0);
}
</script>
<h2>我是第2222个界面</h2>
<button id="btn1">后退</button>
<script>
let oBtn1 = document.querySelector("#btn1");
oBtn1.onclick = function(){
// 后退
// window.history.back();
window.history.go(-1);
};
// 注意点:
// 只有当前访问过其它的界面, back/go方法后退
// 如果给go方法传递-1, 就代表后退1个界面, 传递-2就代表后退2个界面
</script>
三、获取元素的宽高
<style>
*{
margin: 0;
padding: 0;
}
div{
width: 100px;
height: 100px;
padding: 50px;
border: 50px solid #000;
background: red;
background-clip: content-box;
}
</style>
<div id="box"></div>
1.getComputedStyle
- 1.1 获取的宽高不包括 边框和内边距
- 1.2 既可以获取行内(js)设置的宽高,也可以获取CSS设置的宽高
- 1.3 只支持获取, 不支持设置
- 1.4 只支持IE9及以上浏览器
let oDiv = document.querySelector("#box");
// oDiv.style.width = "200px";
// oDiv.style.height = "200px";
// 通过getComputedStyle获取宽高,既可以获取到js设置的宽高,也可以获取到CSS设置的宽高
let style = getComputedStyle(oDiv);
// 报错:getComputedStyle 不支持设置宽高
// style.width = "166px";
// style.height = "166px";
console.log(style.width);
console.log(style.height);
2.currentStyle
- 2.1 获取的宽高不包括 边框和内边距
- 2.2 既可以获取行内设置的宽高,也可以获取CSS设置的宽高
- 2.3 只支持获取, 不支持设置
- 2.4 只支持IE9以下浏览器
let oDiv = document.getElementById("box");
// oDiv.style.width = "166px";
// oDiv.style.height = "166px";
let style = oDiv.currentStyle;
// style.width = "166px";
// style.height = "166px";
// console.log(style);
console.log(style.width);
console.log(style.height);
3.style
- 3.1 获取的宽高不包括 边框和内边距
- 3.2 只能获取行内设置的宽高,不能获取CSS设置的宽高
- 3.3 可以获取,也可以设置
- 3.4 高级低级浏览器都支持
let oDiv = document.getElementById("box");
// style:只能获取js设置的宽高,不能获取CSS设置的宽高!
oDiv.style.width = "166px";
oDiv.style.height = "166px";
console.log(oDiv.style.width);
console.log(oDiv.style.height);
4.offsetWidth和offsetHeight
- 4.1 获取的宽高包含 边框 + 内边距 + 元素宽高
- 4.2 既可以获取行内设置的宽高,也可以获取CSS设置的宽高
- 4.3 只支持获取, 不支持设置
- 4.4 高级低级浏览器都支持
var oDiv = document.getElementById("box");
oDiv.style.width = "166px";
oDiv.style.height = "166px";
// offsetWidth和offsetHeight:只支持获取, 不支持设置
// oDiv.offsetWidth = "166px";
// oDiv.offsetHeight = "166px";
console.log(oDiv.offsetWidth);
console.log(oDiv.offsetHeight);
总结:
- 1.getComputedStyle/currentStyle/style
- 获取的宽高不包括 边框和内边距
- 2.offsetWidth/offsetHeight
- 获取的宽高包括 边框和内边距
- 3.getComputedStyle/currentStyle/offsetXXX
- 只支持获取, 不支持设置
- 4.style
- 可以获取, 也可以设置
- 5.getComputedStyle/currentStyle/offsetXXX
- 既可以获取行内,也可以获取外链和内联样式
- 6.style
- 只能获取行内样式
四、javascript 三大家族
1.offset 相关属性
(1).offsetLeft 和 offsetTop 作用
- offsetLeft / offsetTop:获取元素到第一个定位祖先元素之间的偏移位
- 如果没有祖先元素是定位的, 那么就是获取到body的偏移位
<style>
*{
margin: 0;
padding: 0;
}
.father{
width: 200px;
height: 200px;
margin-top: 100px;
margin-left: 100px;
background: blue;
overflow: hidden;
position: relative;
}
.son{
width: 100px;
height: 100px;
margin-top: 100px;
margin-left: 100px;
background: red;
}
</style>
<div class="father">
<div class="son"></div>
</div>
<script>
let oSDiv = document.querySelector(".son");
oSDiv.onclick = function () {
// 获取元素到第一个定位祖先元素之间的偏移位
console.log(oSDiv.offsetLeft);
console.log(oSDiv.offsetTop);
}
}
</script>
(2).offsetParent 作用
- offsetParent:获取元素的第一个定位的祖先元素
- 如果没有祖先元素是定位的, 那么就是获取到的就是body
<style>
*{
margin: 0;
padding: 0;
}
.grand-father{
width: 300px;
height: 300px;
margin-top: 100px;
margin-left: 100px;
background: deeppink;
overflow: hidden;
position: relative;
}
.father{
width: 200px;
height: 200px;
margin-top: 100px;
margin-left: 100px;
background: blue;
overflow: hidden;
position: relative;
}
.son{
width: 100px;
height: 100px;
margin-top: 100px;
margin-left: 100px;
background: red;
}
</style>
<div class="grand-father">
<div class="father">
<div class="son"></div>
</div>
</div>
<script>
let oSDiv = document.querySelector(".son");
oSDiv.onclick = function () {
// 获取第一个定位的祖先元素
console.log(oSDiv.offsetParent);
}
</script>
2.client 相关属性
- offset 相关属性
- offsetWidth = 宽度 + 内边距 + 边框
- offsetHeight = 高度 + 内边距 + 边框
- client 相关属性
- clientWidth = 宽度 + 内边距
- clientHeight = 高度 + 内边距
<style>
* {
margin: 0;
padding: 0;
}
div {
width: 100px;
height: 100px;
padding: 30px;
border: 60px solid #000;
background: red;
background-clip: content-box;
}
</style>
<div id="box"></div>
let oDiv = document.querySelector("#box");
console.log(oDiv.clientHeight); // 160 = 100 + 30*2
console.log(oDiv.clientWidth); // 160 = 100 + 30*2
- offsetLeft / offsetTop:距离 第一个定位祖先元素(如果没有即为body)的偏移位
- clientLeft / clientTop:左边框 和 顶部边框
console.log(oDiv.clientLeft); // 60
console.log(oDiv.clientTop); // 60
3.scroll 相关属性
(1).scrollWidth 与 scrollHeight 作用
1.1 内容没有超出元素范围时
- scrollWidth = 元素宽度 + 内边距宽度 == clientWidth
- scrollHeight = 元素高度 + 内边距的高度 == clientHeight
<style>
* {
margin: 0;
padding: 0;
}
div {
width: 100px;
height: 100px;
padding: 30px;
border: 60px solid #000;
background: red;
background-clip: content-box;
color: deepskyblue;
overflow: auto;
}
</style>
<div id="box">
我是内容<br />
我是内容<br />
我是内容<br />
我是内容<br />
我是内容<br />
我是内容<br />
我是内容<br />
我是内容<br />
我是内容<br />
我是内容<br />
我是内容<br />
我是内容<br />
我是内容<br />
我是内容<br />
我是内容<br />
我是内容<br />
我是内容<br />
</div>
let oDiv = document.querySelector("div");
console.log(oDiv.scrollWidth); // 160
console.log(oDiv.scrollHeight); // 160
1.2 内容超出元素范围时
- scrollWidth = 元素宽度 + 内边距宽度 + 超出的宽度
- scrollHeight = 元素高度 + 内边距的高度 + 超出的高度
let oDiv = document.querySelector("div");
console.log(oDiv.scrollWidth);
console.log(oDiv.scrollHeight);
(2).scrollTop 和 scrollLeft 作用
- scrollTop:超出元素内边距顶部的距离
- scrollLeft:超出元素内边距左边的距离
let oDiv = document.querySelector("div");
oDiv.onscroll = function () {
console.log(oDiv.scrollTop);
}
五、获取网页的宽高
(1).只能在IE9以及IE9以上的浏览器中才能获取
- innerWidth / innerHeight
console.log(window.innerWidth);
console.log(window.innerHeight);
(2).可以用于在IE9以下的浏览器的标准模式中获取
// documentElement:整个html文件内容
// console.log(document.documentElement);
- 浏览器在渲染网页的时候有两种模式"标准模式"/"混杂模式/怪异模式"
- 默认情况下都是以标准模式来进行渲染的(CSS1Compat),如果网页没有书写文档声明, 那么就会按照"混杂模式/怪异模式"来进行渲染的(BackCompat)
- 2.1 在标准模式中,获取可视区域的宽高
- document.documentElement.clientWidth
- document.documentElement.clientHeight
console.log(document.compatMode); // CSS1Compat
console.log(document.documentElement.clientWidth);
console.log(document.documentElement.clientHeight);
- 2.2 在混杂模式中,获取可视区域的宽高
-
document.body.clientWidth
-
document.body.clientHeight
-
console.log(document.compatMode); // BackCompat
console.log(document.body.clientWidth);
console.log(document.body.clientHeight);
兼容性写法:
let { width, height } = getScreen();
console.log(width);
console.log(height);
// 获取网页的宽高
function getScreen() {
let width, height;
if (window.innerWidth) {
width = window.innerWidth;
height = window.innerHeight;
} else if (document.compatMode === "BackCompat") {
width = document.body.clientWidth;
height = document.body.clientHeight;
} else {
width = document.documentElement.clientWidth;
height = document.documentElement.clientHeight;
}
return {
width: width,
height: height
}
}
六、获取网页的滚动距离
- IE9以及IE9以上的浏览器
-
window.pageXOffset / window.pageYOffset
-
-
标准模式下浏览器
-
document.documentElement.scrollTop
-
document.documentElement.scrollLeft
-
-
混杂(怪异)模式下浏览器
-
document.body.scrollTop
-
document.body.scrollLeft
-
<style>
* {
margin: 0;
padding: 0;
}
p {
line-height: 50px;
width: 200%;
}
</style>
<p>我是正文1</p>
...
<p>我是正文2</p>
<script>
window.onscroll = function () {
// 1.IE9以及IE9以上的浏览器
// console.log(window.pageXOffset);
// console.log(window.pageYOffset);
// 2.标准模式下浏览器
// console.log(document.documentElement.scrollTop);
// console.log(document.documentElement.scrollLeft);
// 3.混杂(怪异)模式下浏览器
// console.log(document.body.scrollTop);
// console.log(document.body.scrollLeft);
}
</script>
兼容性写法:
let { x, y } = getPageScroll();
console.log(x, y);
// 获取网页的滚动距离
function getPageScroll() {
let x, y;
if (window.pageXOffset) {
x = window.pageXOffset;
y = window.pageYOffset;
} else if (document.compatMode === "BackCompat") {
x = document.body.scrollLeft;
y = document.body.scrollTop;
} else {
x = document.documentElement.scrollLeft;
y = document.documentElement.scrollTop;
}
return {
x: x,
y: y
}
}
七、函数防抖
(1).什么是函数防抖 [ debounce ]
- 函数防抖:是优化高频率执行js代码的一种手段
- 可以让被调用的函数,在一次连续的高频操作过程中,只被调用一次
(2).函数防抖作用
- 减少代码执行次数, 提升网页性能
(3).函数防抖应用场景
- oninput / onmousemove / onscroll / onresize 等事件
<input type="text">
<script>
let oInput = document.querySelector("input");
let timerId = null;
// 实时监听用户输入
oInput.oninput = function () {
// 默认每输入一个字符便发送一次网络请求,这样很消耗性能
// console.log(this.value);
// console.log("发送网络请求");
// 如果是连续输入的(假设不超过1s),就只发送一次网络请求,提高性能
// && 当timerId存在(定时器已经开启),才会执行clearTimeout(timerId)(关闭定时器)
timerId && clearTimeout(timerId);
// 等待1000毫秒=1秒后,再执行函数
timerId = setTimeout(function () {
console.log("发送网络请求");
}, 1000);
}
</script>
(4).封装防抖函数
- 将防抖函数,单独封装到一个js文件中
(function (){
// 防抖函数
function debounce(fn, delay) {
let timerId = null;
return function () {
// 保存当前函数的this
let self = this;
// arguments:所有参数
// 如果有event,就是保存保存当前函数的event事件对象
let args = arguments;
timerId && clearTimeout(timerId);
timerId = setTimeout(function () {
// console.log("发送网络请求");
// fn();
// 修改fn中的this与event
fn.apply(self, args);
}, delay || 1000);
}
}
window.debounce = debounce;
})();
- 调用防抖函数
<input type="text">
<script src="js/tools.js"></script>
<script>
let oInput = document.querySelector("input");
function test(event) {
// console.log("发送网络请求");
console.log(this);
console.log(event);
}
// 调用防抖函数
oInput.oninput = debounce(test);
// oInput.oninput = debounce(test, 5000);
</script>
(5).防抖函数-练习
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>防抖函数-练习</title>
<style>
*{
margin: 0;
padding: 0;
}
div{
width: 200px;
height: 200px;
background: red;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
</style>
</head>
<body>
<div></div>
<script src="js/tools.js"></script>
<script>
/* 需求: 让div的宽高永远是可视区域宽高的一半 */
let oDiv = document.querySelector("div");
function resetSize(){
let { width, height } = getScreen();
oDiv.style.width = width / 2 + "px";
oDiv.style.height = height / 2 + "px";
}
// // 监听可视区域尺寸变化事件
// window.onresize = function(){
// resetSize();
// console.log("尺寸的变化");
// }
// 只要可视区域(浏览器)尺寸发生变化,就会调用resetSize函数,尺寸频繁发生变动,就会频繁调用resetSize函数,进而产生性能问题,此时便可利用防抖函数进行优化代码
// 调用封装好的防抖函数
window.onresize = debounce(resetSize, 1000)
</script>
</body>
</html>
八、函数节流
(1).什么是函数节流 [ throttle ]
- 函数节流也是优化高频率执行js代码的一种手段
- 可以减少高频调用函数的执行次数
(2).函数节流作用
- 减少代码执行次数, 提升网页性能
(3).函数节流应用场景
- oninput / onmousemove / onscroll / onresize 等事件
(4).函数节流和函数防抖区别
- 函数节流是减少连续的高频操作函数执行次数 (例如连续调用10次, 可能只执行3 - 4次)
- 函数防抖是让连续的高频操作时函数只执行一次 (例如连续调用10次, 但是只会执行1次)
let timerId = null;
let flag = true;
window.onresize = function () {
if (!flag) {
return;
}
flag = false;
timerId && clearTimeout(timerId);
timerId = setTimeout(function () {
flag = true;
resetSize();
// console.log("尺寸的变化");
}, 500);
}
(5).封装节流函数
(function (){
// 节流函数
function throttle(fn, delay) {
let flag = true;
let timerId = null;
return function () {
if (!flag) {
return;
}
flag = false;
let self = this;
let args = arguments;
timerId && clearTimeout(timerId);
timerId = setTimeout(function () {
flag = true;
fn.apply(self, args);
}, delay || 1000);
}
}
window.throttle = throttle;
})();