一、浏览器JS的执行态
- ECMAScript - 基础逻辑、数据处理
- DOM - 对于浏览器是视窗内,文本的对应操作
- BOM - 对于浏览器本身区域能力的处理
二、BOM
1. location
- .href => 'www.baidu.com/search?clas…' => 路径栏所有
- .orgin => 'www.baidu.com' => 域名部分
- .protocol => 'https:' => 协议部分
- .host => 'www.baidu.com' => 域名不包括协议部分
- .port => '' => 端口号
- .pathname => '/search' => 域名之后的路径名
- .search => '?class=1' => 搜索部分
- .hash => '#comment' => 哈希值
方法
- assign('') // 跳转到制定path => 替换pathname
- replace('') //不仅替换pathname,同事替换浏览历史(浏览器不能返回)
- reload('') //刷新
- toString() //产出当前地址字符串
2. history
- history.state => 储存当前页面的状态
浏览器不会刷新,刷新了模板区域
- history.pushState()
- history.replaceState()
路由方向history和hash的模式的区别
- hash 模式带有
#较丑,history 模式较简洁 - pushState 设置的新 URL 可以是与当前 URL 同源的任意 URL;而 hash 只可修改 # 后面的部分,故只可设置与当前同文档的 URL
- pushState 设置的新 URL 可以与当前 URL 一模一样,这样也会把记录添加到栈中;而 hash 设置的新值必须与原来不一样才会触发记录添加到栈中
- pushState 通过 stateObject 可以添加任意类型的数据到记录中;而 hash 只可添加短字符串
- pushState 可额外设置 title 属性供后续使用
- hash 兼容IE8以上,history 兼容 IE10 以上
- history 模式需要后端配合将所有访问都指向 index.html,否则用户刷新页面,会导致 404 错误
3.navigator
浏览器系统信息集合
- userAgent //获取用户的环境信息
- 读取信息 => 浏览器兼容、上报信息
- 剪切板、键盘
4.screen
表征显示区域 - 荧幕
判断区域大小:
-
window视窗判断:
- 全局入口处:
- window.innerHeight
- window.innerWidth
- 文本处获取:
- document.documentElement.clinetHeight
- document.documentElement.clinetWidth
- 全局入口处:
-
网页视图的size -> offsetHeight = clientHeight + 滚动条 + 边框:
- document.documentElement.offsetHeight
- document.documentElement.offsetWidth
-
动态定位:
- scrollLeft / scrollTop -距离常规左 / 上滚动的距离
- offsetLeft / offfsetTop -距离常规左 / 上的距离
-
el.getBoundingClientRect().
- el.getBoundingClientRect().top
- el.getBoundingClientRect().left
- el.getBoundingClientRect().bottom
- el.getBoundingClientRect().right
兼容性问题 IE会多出来2像素
三、 Event事件模型
<div id='app'>
<p id='dom'/>
</div>
// 冒泡 -ms: p => div => body => HTML => document
// 捕获 -ns: document => HTML => body => div => p
el.addEventListener(event, function, useCapture) //默认false (冒泡)
// 追问
// 1. 如何阻止事件的传播
event.stopPropogation() 阻止冒泡 (阻止传递行为 无法阻止默认事件)
event.preventDefault() 阻止捕获、默认事件
event.stopImmediatePropagation() 相同节点绑定多个同类事件 会立刻阻止该节点上的所有同类事件
// 兼容性
// 2. 手写兼容性事件绑定
// IE -attachEvent vs addEventListener
// 区别
// a. 传参 attachEvent 事件名需要加上'on'
// b. 执行顺序 attachEvent:后绑定先执行 addEventListener:先绑定先执行
// c. 解绑: detchEvent vs removeEventListener
// d. 阻断 event.cancelBubble vs event.stopPropogatio
// e. 默认事件拦截 event.returnValue vs event.preventDefault()
// 3.性能优化 - 事件代理
<ul class='list'>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
</ul>
var list = document.querySelector('list');
var li = list.getElementsByTagName('li');
// 硬碰硬 动态列表或者很多li性能有问题
for(var n = 0; n < li.length; n++){
li[n].addEventListener('click', function(){});
}
// 代理后 - 利用事件传递
function onClick(e){
var e = e || window.event;
if(e.target.nodeName.toLowCase() === 'li'){
var list = this.querySelevctiorAll('li');
// 业务逻辑 对比点击的是哪个li
}
}
list.addEventListener('click', onClick);
四、网络层
// 实例化
const xhr = new XMLHttpRequest();
// 初始化建立
xhr.open(method, url, async) // get/post; 请求地址; 是否为异步请求
// 方法的发送请求 - send
xhr.send(data) // get - 可以不传火传入null, post -encodeURIComponent编码拼接
// 接收
// xhr.readyStatus: 0 - 尚未建立open; 1 - 已经调用open; 2 - 已经调用send; 3 - 已经收到请求返回的数据; 4 - 请求已经完成。 经常用4判断, 为什么用4
xhr.onreadystatechange = () => {
if(xhr.readyStatus === 4){
// 判断http状态码
if(xhr.status >= 200 && xhr.status < 300 || xhr.status === 300){
//接口返回成功
}
}
}
// 超时时间
xhr.timeout = 30000;
xhr.ontimeout = () => {
//超时后
}
// 封装手写
ajax({
url: 'reqUrl',
methor: 'get',
async: true,
timeout: 30000,
data: {
payload: 'text'
}
}).then(
res => {}
err => {}
)
// 实现手写
function ajax(options){
const {
url,
method,
async,
data,
timeout
} = options;
const chr = new XMLHttpRequest();
// 配置超时时间
if(timeout){
chr.timeout = timeout;
}
return new Promise((resolve, reject) => {
// 成功
chr.onreadystatechange = () => {
if(chr.readyStatus === 4){
// 判断http状态码
if(chr.status >= 200 && chr.status < 300 || chr.status === 300){
//接口返回成功
resolve(chr.responseText)
} else {
reject && reject();
}
}
}
// 失败
chr.onerror = err => reject(err)
// 传参处理
let _params = [];
let encodeData = '';
if(data instanceof Object){
for(let key in data){
// 参数编码
_params.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))
}
encodeData = _params.join('&')
}
// method 判断连接
if(method === 'get'){
const index = url.indexOf('?');
if(index === -1){
url += '?';
} else if(index !== url.length -1){
url += '&';
}
url += encodeData;
}
// 建立连接
chr.open(methor, url, async);
// 发送请求
if(method === 'get'){
xhr.send(null);
} else {
xhr.setRequestHeader(
'content-type': 'application/x-www-form-urlencoded'
)
xhr.send(encodeData)
}
})
}
面试方向
- TCP => HTTP/HTTPS
- 状态码 => 2xx(成功) 4xx(客户端出错) 5xx(服务端错误) | 3xx => 浏览器缓存 => 强缓存(Expires + cache-control) / 协商缓存 (last-modified + Etag)
- content-type => 内容类型 => 浏览器 => ff chrome
五、浏览器原理
面试题: 从url输入到页面展示发生了什么 - 获取到资源 =》 渲染出页面
浏览器渲染流程
- DOM
- CSSOM - CSS解析成树形数据结构
- Render Tree: DOM + CSSOM生成树
- Layout module: 计算Render Tree每个节点具体的状态和位置
- Painting: 呈现到屏幕上
URL => HTML解析 - JS + DOM + CSSOM => render tree / JS + css执行 => layout module => painting
纵向切分
bytes => characters() => Tokens(解析成抽象语法树 tag tree) => Nodes(html|head|body) characters => Tokens 解析成计算机读得懂的语言