Skip to content

Latest commit

 

History

History
247 lines (157 loc) · 7.84 KB

浏览器.md

File metadata and controls

247 lines (157 loc) · 7.84 KB

关于事件

三个阶段

  1. window往事件处发处传播遇到注册的捕获事件会触发
  2. 传播到事件触发处时触发注册的事件
  3. 从事件触发处往window传播,形成冒泡,注册的冒泡事件会被触发

注册事件方法

通常用addEventListener(),

node.addEventListener(
	'click', // 事件类型
    () => {}, // 回调函数
    Boolean || { // 第三个参数可以是布尔值,也可以是对象, 布尔true是捕获, false是冒泡, 默认false
        capture: true || false, // 和布尔意思一样
        once: Boolean, // 是不是只执行一次
        passive: Boolean // 是不是可以取消默认行为
    }
    
)

事件代理

<ul id="ul">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
</ul>
<script>
  let ul = document.querySelector('#ul')
  ul.addEventListener('click', event => { // 只监听父元素
    console.log(event.target)
  }) // 优点: 节省内存,不需要关心子组件的事件
</script>

关于跨域

JSONP

原理:

​ 利用<script> 标签没有跨域限制的漏洞

​ 仅限于 get 请求

自己封装JSONP

function JSONP(url, jsonpCallBack, success) {
    let script = document.createElement('script');
    script.url = url;
    script.async = true;
    window[jsonpCallBack] = function (data) {
        success && (data);
    }
    document.body.appendChild(script);
}
jsonp('http://', 'callback', function (value) {
    console.log(value)
})

使用JSONP时对服务端传递的数据也是有要求的

CORS

CORS 需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。

浏览器会自动进行 CORS 通信,实现 CORS 通信的关键是后端。只要后端实现了 CORS,就实现了跨域。

服务端设置 Access-Control-Allow-Origin 就可以开启 CORS。 该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源

document.domain

该方式只能用于二级域名相同的情况下,比如 a.test.comb.test.com 适用于该方式。

只需要给页面添加 document.domain = 'test.com' 表示二级域名都相同就可以实现跨域

postMessage

这种方式通常用于获取嵌入页面中的第三方页面数据。一个页面发送消息,另一个页面判断来源并接收消息

// 接收消息
window.parent.postMessage('message', 'http://test.com')
// 接收消息端
var mc = new MessageChannel()
mc.addEventListener('message', event => {
  var origin = event.origin || event.originalEvent.origin
  if (origin === 'http://test.com') {
    console.log('验证通过')
  }
})

EventLoop 事件环

因为JS当时设计是为操作DOM的,所以设计为单线程比较方便,比如如果一个线程创建DOM,另一个线程删除DOM,就搞笑了

JS在执行时会有执行环境, 这些执行环境会按规则加入到执行栈中,如果遇到异步代码,则挂起到task中,如果执行栈为空,就会从task里面取出异步代码执行

掌握事件环,一定掌握

  • 宏任务:scriptsetTimeoutsetIntervalsetImmediateI/OUI rendering

  • 微任务:process.nextTickpromiseObject.observeMutationObserver

先执行同步代码,然后微任务,然后宏任务

1. 函数入栈,当Stack中执行到异步任务的时候,就将他丢给WebAPIs,接着执行同步任务,直到Stack为空;
2. 此期间WebAPIs完成这个事件,把回调函数放入队列中等待执行(微任务放到微任务队列,宏任务放到宏任务队列)
3. 执行栈为空时,Event Loop把微任务队列执行清空;
4. 微任务队列清空后,进入宏任务队列,取队列的第一项任务放入Stack(栈)中执行,回到第1步。

浏览器存储

cookie, localStorage, sessionStorage, IndexDB

特性 Cookie localStorage sessionStroage IndexDB
数据生命周期 服务器生成,可以设置过期时间 除非被清理,否则一直存在 页面关闭就清理 除非被清理,否则一直存在
数据储存大小 4k 5m 5m 无限
与服务端通讯 强缓存不会在请求头里出现, 协商缓存每一次会在请求头出现,如果服务器显示缓存可用,则会返回代码304,因为每一次都在请求头里,所以会有性能影响 不参与 不参与, 不能在同源窗口共享 不参与

session 是存储在服务器中的

Service Worker

service worker充当应用程序和浏览器之间的代理服务器,也可以在网络可用时充当浏览器和网络的代理,目前该技术用作缓存文件提高首屏速度

浏览器渲染机制

浏览器渲染分为以下几个步骤

  1. 处理html构建DOM树
  2. 处理CSS构建CSSOM树
  3. 将DOM和CSSOM合并为一个渲染树
  4. 根据渲染树布局,并计算元素位置
  5. 调用GPU绘制,显示在屏幕上

注意事项:

  1. 构建CSSOM树会阻塞渲染,并且CSSOM树的绘制十分消耗性能,越具体的选择器执行速度越慢,所以要保持扁平选择
  2. 当HTML渲染到script标签时,会暂停构建DOM,JS解析完成后再从暂停地方开始,所以首屏想要更快,就别在首屏加载JS,

浏览器图层

了解过PS的都知道图片是一层一层堆积的,浏览器也是这样,并且图层越多性能越差

一行代码让chrome崩溃:

body {
    transform:scale(10000)
}

以下几个属性可以生成新图层,慎用

  • 3D变换: translate3D, translateZ, transform等
  • will-change
  • video, iframe 标签
  • 通过动画实现的opacity转换
  • position: fixed

重绘与回流

重绘与回流是渲染机制中的一部分

  • 重绘就是不改变布局,元素大小等,只改变元素表现的比如颜色,透明度等
  • 回流就是改变元素大小的,整个网页需要重新绘制

回流性能成本比重绘高得多

重绘不一定导致回流,回流一定导致重绘

以下几个动作会导致重绘或回流

  1. window大小改变
  2. 改变字体
  3. 添加或删除样式
  4. 文字改变
  5. 定位或浮动
  6. 盒模型

重绘和回流与Event Loop有关

  1. 当 Event loop 执行完 Microtasks 后,会判断 document 是否需要更新。因为浏览器是 60Hz 的刷新率,每 16ms 才会更新一次。
  2. 然后判断是否有 resize 或者 scroll ,有的话会去触发事件,所以 resizescroll 事件也是至少 16ms 才会触发一次,并且自带节流功能。
  3. 判断是否触发了 media query
  4. 更新动画并且发送事件
  5. 判断是否有全屏操作事件
  6. 执行 requestAnimationFrame 回调
  7. 执行 IntersectionObserver 回调,该方法用于判断元素是否可见,可以用于懒加载上,但是兼容性不好
  8. 更新界面
  9. 以上就是一帧中可能会做的事情。如果在一帧中有空闲时间,就会去执行 requestIdleCallback 回调。

如何减少重绘与回流

  1. 使用translate代替top
  2. 使用visibility代替display:none
  3. 把DOM离线后修改(先设置为display: none, 然后修改完成后插入)
  4. 不要把DOM节点属性放到循环里去
  5. 尽量不要使用table布局
  6. 实现动画,动画越快,回流次数越多,可以使用requestAnimationFrame
  7. CSS 选择符从右往左匹配查找,避免 DOM 深度过深
  8. 将频繁运行的动画变为图层,图层能够阻止该节点回流影响别的元素。比如对于 video 标签,浏览器会自动将该节点变为图层。