浏览器对象模型
BOM:Browser Object Model(浏览器对象模型),浏览器模型提供了独立于内容的,可以与浏览器窗口进行互动的对象结构。主要的API:
1) window: 是BOM的核心,是js访问浏览器的接口
常见方法:alert、confirm、prompt、open、onerror、setTimeout、setInterval
2) location对象:提供当前窗口中加载的文档有关的信息和一些导航功能
常见方法:hash、host、hostname、href、port、protocol、search
3) navigator对象: 获取浏览器的系统信息
4) screen对象: 表示浏览器显示器的相关信息
常见方法:screenX, screenY, screenLeft、screenTop, moveBy(x, y), moveTo(x, y)
5) history对象: 存储用户上网的历史记录(重点,vue-router和react-router就是基于这个api实现的)
常见方法:pushState, onPopState, push, back, forward, go
浏览器事件机制
事件委托/事件代理
执行顺序?
捕获阶段 -> 目标阶段 -> 冒泡阶段
如果触发的是一个button上的click事件
则执行顺序为(默认情况下是先事件捕获后事件冒泡): window -> body -> button -> body -> window
在js中的addEventListener有三个参数,第三个参数用来控制事件是冒泡的阶段触发,还是在捕获的阶段
触发,默认是false。
阻止事件的传播
e.stopPropagation() //符合W3C标准的浏览器
阻止默认行为
e.preventDefault() // 标准浏览器
项目中使用场景
在C端小程序中,某个页面只有当有某种权限的时候才能进行一些交互,这种情况下该如何处理?
方案一:
给整个页面添加一个蒙层,判断是否有访问权限,若有则正常显示,反之则展示蒙层。这样有一个缺陷就是增加了页面元素。
方案二:
利用事件委托机制,在最外层的DOM结构上绑定事件,在捕获阶段触发,先判断是否有权限。
解决兼容性问题
class BomEvent {
constructor (element) {
this.element = element;
}
addEvent (type, handler) {
if (this.element.addEventListener) {
this.element.addEventListener(type, handler, false);
} else if (this.element.attachEvent) {
this.element.attachEvent(`on${type}`, handler);
} else {
this.element[`on${type}`] = handler;
}
}
removeEvent (type, handler) {
if (this.element.removeEventListener) {
this.element.removeEventListener(type, handler);
} else if (this.element.detachEvent) {
this.element.detachEvent(`on${type}`, handler);
} else {
this.element[`on${type}`] = null;
}
}
}
function stopPropagation (evt) {
if (evt.stopPropagation) {
evt.stopPropagation();
} else {
// 兼容IE
evt.cancelBubble = true;
}
}
function preventDefault (evt) {
if (evt.preventDefault) {
evt.preventDefault();
} else {
// 兼容IE
evt.returnValue = false;
}
}
ajax和 fetch api详解 !important
原生ajax 基于XMLHttpRequest api发送请求
const xhr = new XMLHttpRequest()
xhr.open('GET', 'https://www.baidu.com')
// 这里需要注意的是: 要先建立状态的监听,然后再使用send方法发送请求
xhr.onreadystatechange = () => {
// readyState为4时代表请求完成
if(xhr.readyState !== 4) {
return
}
// 请求成功
if(xhr.status === 200) {
console.log(xhr.responseText);
} else {
// 请求失败
console.error('error', xhr.statusText);
}
}
// 原生ajax自带超时的api
xhr.timeout = 3000
xhr.ontimeout = () => {
console.log('当前请求已超时');
}
xhr.send()
fetch 也是原生发送请求的api,是基于promise封装的,可以.then、.catch。
fetch('http://www.baidu.com',{
method: 'GET',
credentials: 'same-origin'
}).then(response =>{
if(response.ok) {
return response.json()
}
throw new Error('request error')
}).catch(err =>{
console.error(err)
})
// 这样问题就来了,基于fetch发送的请求如何实现超时呢?这里需要指出的是fetch原生没有支持超时的api
function fetchTimeout(url, init, timeout = 3000) {
return new Promise((resolve, reject) =>{
fetch(url, init).then(resolve).catch(reject)
setTimeout(reject, timeout)
})
}
summary: 虽然说发送请求可以使用原生的ajax和fetch,但是实际的企业中项目还是使用axios库来封装发送请求的逻辑比较多。
请求头
method: 请求方法
path: 请求路径
cookie: 与用户信息相关的一些信息
referer: 页面来源
user-agent: 用来对不同的设备做不同的处理
响应头
access-control-allow-origin: * //浏览器同源的问题
content-encoding: gzip
set-cookie: //例如:login接口可能返回一些认证成功的信息,就是通过这个响应头的字段种到页面
中
常见的请求状态
200: get请求成功
201: post请求成功
301: 永久重定向
302: 临时重定向
304: 协商缓存: 避免重复发送相同请求的一种策略
400: 客户端请求参数错误:客户端参数与服务端要求参数不同 导致报错
404: 未找到相应请求地址,可以是客户端地址错误,也有可能是域名还没有部署到生产环境
405: 请求方式错误, get或者post、put等请求方式与后端要求不对应