跳到主要内容

BOM

BOM 基础

BOM
  • Browser Object Model;
  • 浏览器对象模型;

window 对象

窗口关系

基本概念
windows.top; // 指向浏览器顶层窗口
windows.parent; // 当前窗口的父窗口, 若无窗口即 windows.top
windows.self; // windows 本身
窗口位置
windows.screenLeft; // 窗口左侧位置的像素值
windows.screenTop; // 窗口顶部位置的像素值
移动窗口
// 将窗口移动至 (x, y) 对应的绝对位置
window.moveTo(0, 50); // 0, 50
// 把窗口相对移动 (x, y)
window.moveBy(0, 100); // 0, 150
像素比
// 物理像素: 屏幕实际分辨率
// 逻辑像素: 浏览器转换后的虚拟分辨率
// 表示物理像素和逻辑像素的比值, 与 DPI 对应
window.devicePixelRatio;

窗口大小

大小相关属性
// 浏览器窗口大小
let pageWidth = window.outerWidth;
let pageHeight = window.outerHeight;
// 浏览器窗口中页面视口大小
let pageWidth = window.innerWidth;
let pageHeight = window.innerHeight;
精准获得页面视口大小
// 获得页面视口大小
let pageWidth = window.innerWidth,
pageHeight = window.innerHeight;
// 未获取成功
if (typeof pageWidth != "number") {
// 判断页面是否为标准模式, 通过 document.documentElement 获取大小
if (document.compatMode == "CSS1Compat") {
pageWidth = document.documentElement.clientWidth;
pageHeight = document.documentElement.clientHeight;
} // 否则通过 document.body 获取大小
else {
pageWidth = document.body.clientWidth;
pageHeight = document.body.clientHeight;
}
}
调整窗口大小
// 缩放至 (w, h)
window.resizeTo(100, 100); // 100 * 100
// (w, h) + (w, h)
window.resizeBy(100, 50); // 200 * 150

视口位置

视口位置
// 相对于页面视口的位置
window.scrollX; // x 相对位置
window.scrollY; // y 相对位置
滚动视口
// 相对于当前视口向下滚动 100 像素
window.scrollBy(0, 100);
// 相对于当前视口向右滚动 40 像素
window.scrollBy(40, 0);
// 滚动到页面左上角
window.scrollTo(0, 0);
// 正常滚动
window.scrollTo({
left: 100,
top: 100,
behavior: "auto",
});
// 平滑滚动
window.scrollTo({
left: 100,
top: 100,
behavior: "smooth",
});

系统对话框

// console.log() 为警告框
// confirm() 为确认框, 点击确认返回 true, 反之返回 false
if (confirm("Are you sure?")) {
console.log("I'm so glad you're sure!");
} else {
console.log("I'm sorry to hear you're not sure.");
}

// prompt() 为提示框, 第一个参数为显示文本, 第二个参数为输入默认值
// 点击确认返回输入值, 反之返回 null
let result = prompt("What is your name? ", "");
if (result !== null) {
console.log("Welcome, " + result);
}

导航与打开新窗口

// 打开至指定 url, 并指定在 topFrame 窗口页打开
window.open("http://www.wrox.com/", "topFrame");

global 作用域

机制
// window 复用为 ECMAScript 的 Global 对象
// 任何 var 声明的变量和函数为其属性和方法
var age = 29;
var sayAge = () => console.log(this.age);
window.age; // 29
window.sayAge(); // 29

定时器

setTimeout()
  • setTimeout(functionRef,delay,param1,param2,/_ … ,_/ paramN);
    • 第一个参数表示回调函数,第二个参数为等待时间;
    • 其余参数为传递给 fn 的函数参数;
  • clearTimeout(timeoutId):取消定时任务;
let timeoutId = setTimeout(() => console.log("Hello world!"), 1000);
clearTimeout(timeoutId);
setInterval()
  • setInterval(functionRef,delay,param1,param2,/_ … ,_/ paramN);
    • 第一个参数表示回调函数,第二个参数为循环时间;
    • 其余参数为传递给 fn 的函数参数;
  • clearInterval(timeoutId):取消循环任务;
let timeoutId = setInterval(() => console.log("Hello world!"), 10000);
clearInterval(timeoutId);
setIntervale() 的局限
  • 两个任务之间的时间间隔无法保证;
  • 有可能会跳过部分任务;

location 对象

location 基础

location
  • 保存窗口文档信息;
  • window.location 和 document.location 都指向它;
属性
location.hash; // url 散列值
location.host; // 服务器名:端口名
location.hostname; // 服务器名
location.href; // 当前窗口的 url
location.pathname; // host 后的路径
location.port; // 端口名
location.protocol; // http/https
location.search; // url 查询字符串, 以 ? 开头
location.username; // 用户名
location.password; // 密码
location.origin; // url 源地址

查询字符串

let qs = "?q=javascript&num=10";
// 创建 URLSearchParams
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"

操作地址

设置地址
// 使用 assign()
location.assign("http://www.wrox.com");
// 以下两者隐式调用 assign()
window.location = "http://www.wrox.com";
location.href = "http://www.wrox.com";
修改地址
// 设置当前 URL 为 http://www.wrox.com/WileyCDA/
location.assign("http://www.wrox.com/WileyCDA/");
// 把 URL 修改为 http://www.wrox.com/WileyCDA/#section1
location.hash = "#section1";
// 以下方法会刷新页面
// 把 URL 修改为 http://www.wrox.com/WileyCDA/?q=javascript
location.search = "?q=javascript";
// 把 URL 修改为 http://www.somewhere.com/WileyCDA/
location.hostname = "www.somewhere.com";
// 把 URL 修改为 http://www.somewhere.com/mydir/
location.pathname = "mydir";
// 把 URL 修改为 http://www.somewhere.com:8080/WileyCDA/
location.port = 8080;
// 把 URL 修改为 http://www.wrox.com/
// 该方法不添加历史记录, 无法使用浏览器返回功能
location.replace("http://www.wrox.com/");
// 重新加载该页面
location.reload();
// 重新加载该页面, 并强制从服务器加载
location.reload(true);
  • 记录一系列浏览器信息;

screen 对象

screen
  • 记录客户端显示器信息;
属性
availHeight / Left / Top / Width; // 屏幕像素减去系统组件像素的高度/最左侧像素/顶部像素/宽度
height / left / top / width; // 屏幕像素高度/最左侧像素/顶部像素/宽度
colorDepth; // 屏幕色深
pixelDepth; // 屏幕位深
orientation; // 屏幕朝向

history 对象

history

  • 管理浏览器历史记录;

导航

// 历史记录数量
history.length;
// 后退一页
history.go(-1);
history.back();
// 前进一页
history.go(1);
history.forward();
// 导航到最近的 wrox.com 页面
history.go("wrox.com");

历史状态管理

状态管理 API
  • 改变 URL 而不重新加载页面;
操作历史状态管理
// 加载一个状态信息
let stateObject = { foo: "bar" };
// stateObject 为存储对象, title 为状态标题, baz.html 为相对 url
history.pushState(stateObject, "title", "baz.html");

// 监听 popState 事件, 即后退按钮
window.addEventListener("popstate", (event) => {
let state = event.state; // 获取当前状态
// 第一个页面加载时状态是 null
if (state) {
processState(state); //
}
});

// 更新当前状态
history.replaceState({ newFoo: "newBar" }, "New title");

最佳实践

自动滚动

const autoScroll = () => {
const scroll = async () => {
if (!tagRef.current) return;
else;
// 判断是否可以滚动
if (tagRef.current.scrollWidth <= tagRef.current.clientWidth) return;
else;
// 判断是否滚动至重点
if (
tagRef.current.scrollLeft + tagRef.current.clientWidth ===
tagRef.current.scrollWidth
) {
tagRef.current.scrollLeft = 0;
} else() {
tagRef.current.scrollLeft += 1;
}
intervalRef.current = requestAnimationFrame(scroll);
};

// 判断 DOM
if (!tagRef.current) return;
else;
// 自动滚动
intervalRef.current = requestAnimationFrame(scroll);
// 对应事件处理程序
tagRef.current.onmouseenter = () => {
cancelAnimationFrame(intervalRef.current);
};
tagRef.current.onmouseleave = () => {
intervalRef.current = requestAnimationFrame(scroll);
};
};

使用 setTimeout/setInterval 模拟对方

使用 setTimeout 实现 setInterval
function setInterval(fn, delay) {
let timer = null;
const interval = () => {
fn();
timer = setTimeout(interval, delay);
};
setTimeout(interval, delay);

return {
cancel: () => {
clearTimeout(timer);
},
};
}

const origin = Date.now();
const fn = () => {
console.log(Date.now() - origin);
};
setInterval(fn, 1000);
使用 setInterval 实现 setTimeout
function mySetTimeout(fn, time) {
const timer = setInterval(() => {
clearInterval(timer);
fn();
}, time);

return {
cancel: () => {
clearInterval(timer);
},
};
}

const origin = Date.now();
const fn = () => {
console.log(Date.now() - origin);
};
mySetInterval(fn, 1000);