经典文章how browser works
那么这个问题考察的就是渲染原理方面的知识点,上面就是市面上主要浏览器对应的渲染引擎,通过这个问题我们就引出了我们今天要介绍的内容。可以看到目前Blink渲染引擎占据了半壁江山,当然Blink的前身都是由Webkit优化改造而来的。也正是因为有这些不同的渲染引擎,大家才会遇到浏览器的兼容性问题,相信随着规范的不断推进,需要我们解决的兼容性问题将会越来越少。渲染原理解析关于渲染原理,我们首先来看这张图,如下:
上图就是整个渲染流程的总体流程图,下面我们来一一介绍渲染流程当中的每个步骤。首先是解析HTML,这个过程主要是把HTML文档解析为DOM树的过程。如果遇到标签会停止解析,先执行标签当中JavaScript;如果是外联方式,也需要等待下载并且执行完对应的JavaScript代码,然后才能够继续执行解析HTML的工作。HTML解析完成后触发DOMContentLoaded事件,这里我们就可以操作DOM了。
生成对应的DOM树结构如下:
Tips:上图中的DOM树节点类型如何获取呢,这里我们可以在Chrome当中选中对应元素,然后在控制台中输入$0.constructor,即可打印出对应的类型,如下:
然后是解析CSS。可以看到解析HTML和解析CSS是并行处理的,也就是这两部分是同时进行的,不然会造成渲染的内容没有对应的样式。解析CSS遇到标签和上面解析HTML的处理方法是一样的,这里不在赘述。CSS解析器将CSS解析成CSSStyleSheet(也被叫做CSSOM树),这里的CSSOM树与DOM树结构类似。解析对应关系如下:
接着由DOM树和CSSOM树一起附着合成渲染树(RenderTree),显而易⻅地我们可以得到这个公式:DOMTree+CSSOMTree=RenderTree。同样这里Render树我们也可以简单用图来表示一下,如下:
图中左侧为DOM树,右侧是Render树,可以看到Render树结构与DOM树是非常相似的,但不是一一对应的。每一个节点是一个RenderObject,包含了我们在样式表中设置的样式,样式的宽高和具体位置是通过Layout(重排)计算得出。
Tips:
元素如果被设置为display:none,在DOM树中依然会显示,但是在Render树中不会显示;元素如果被设置为visibility:none,那么DOM树和Render树中都会显示;我们经常说的脱离文档流,其实就是脱离Render Tree。
⻣架,自动化方案,page-skeleton-webpack-plugin,以及antd的skeleton组件
少操作dom,用fragment,虚拟dom
event-loop
一个完整的Event Loop过程,可以概括为以下阶段:
Macrotask/Microtask上面我们提到了任务队列,那么任务队列有两种,一种是Macrotask,另外一种是Microtask。从最开始我给出的Event Loop总的流程图,大家可以看出Microtask优先级是高于Macrotask的。Microtask当中的任务也是在执行栈当中的任务执行完成后再进行执行,执行的时候和Macrotask有一些区别,Microtask当中任务不会一个一个压入执行栈,而是所有任务直接压入栈中,当Microtask当中的任务执行完毕后,然后我们再从Macrotask中取栈顶的第一个任务进行执行。
那么哪些任务属于Microtask,哪些任务属于Macrotask呢,这里我做了一个大概的总结,如下:Macrotask:setTimeout、setInterval、I/O、UIRendering、script当中的所有代码、setImmediate(Node)Microtask:process.nextTick(node)、Promise、MutationObserver
Tips:有一些考察较详细的题目,还会考察Microtask当中各种任务的优先级,具体的优先级如下:
process.nextTick> Promise >MutationOberser
节流隔一段时间只触发一次第一个人说了算在时间结束出发
//func是用户传入需要防抖的函数
//wait是等待时间
防抖
完成后再统一发送请求,最后一个人说了算只认最后一次
图片懒加载
//获取所有的图片标签
constimgs=document.getElementsByTagName('img')
//获取可视区域的高度
constviewHeight=window.innerHeight||document.documentElement.clientHeight
//num用于统计当前显示到了哪一张图片,避免每次都从第一张图片开始检查是否露出
letnum=0
functionlazyload(){
for(leti=num;i(imgs.length;i++) {
//用可视区域高度减去元素顶部距离可视区域顶部的高度
letdistance=viewHeight-imgs[i].getBoundingClientRect().top
//如果可视区域高度大于等于元素顶部距离可视区域顶部的高度,说明元素露出
if(distance>=0){
//给元素写入真实的src,展示图片
imgs[i].src=imgs[i].getAttribute('data-src')
//前i张图片已经加载完毕,下次从第i+1张开始检查是否露出
num=i+1
}
}
}
//监听Scroll事件
window.addEventListener('scroll',lazyload,false);
svg,虚拟列表,300ms延迟(禁用缩放解决)https://bvau g hn. g ithub.io/react-virtualized/#/components/List
ReactpurecomponentVue
async-component
可视化优化
tree-shaking删除冗余代码