js是单线程的,这主要是由于web的特殊性,为了大量IO操作,也为了避免各类冲突,js需要通过大量同步异步操作达到页面效果。
事件有很多种,触发/产生事件的方式也有很多,包括:鼠标、键盘等IO操作的事件,浏览器的一些操作事件(操作DOM,或者window绑定产生的事件),js脚本执行过程中产生的异步任务也是一种事件。这些异步事件,也可以说是任务,级别上有两类:微任务和宏任务
遇到同步事件直接执行,遇到异步事件,根据事件的类别分到不同的任务队列里。这一轮就算执行完成了的。
完成一轮事件后,看微任务队列是否为空,不为空则执行微任务队列里的任务,同样,这些任务里的事件,同步的直接执行,异步继续分类到不同的任务队列里。只有微任务队列为空时,才会执行宏任务队列里的任务。这就是一次循环了。
打个比方,就如同筛选一样:
故:有微则微,无宏才实
对于计算机网络的握手都不提了,主要简略讲拿到资源后的浏览器的解析流程:
浏览器会分析html源码,在DOM树中,每一个HTML标签都有一个对应的节点(元素节点),并且每一个文本也都有一个对应的节点(文本节点)。DOM树的根节点就是documentElement,对应的是html标签。
浏览器会忽略错误的CSS代码,然后根据样式的优先级进行解析,忽略一些选择器的属性,优先级从低到高:浏览器默认设置,用户设置,外联样式,内联样式,行内样式等,这个是有权重的。
渲染树和DOM树很相似,但是不一样。主要区别是DOM树完全和html标签一一对应,但渲染树会忽略不需要渲染的元素,并且渲染树每个节点会留有CSS样式的数据信息。可以认为DOM+样式数据=渲染树。
拿到渲染树后,浏览器根据规则表现视觉效果。
如今Vue框架和React框架都用的虚拟Dom,其就是要了减少频繁dom操作带来的重绘重排带来的性能问题。也就是框架会生成一个虚拟的Dom树,所有操作都会对虚拟dom树进行操作,这也是为什么vue不提倡直接操作document,而要用refs。
vue运行过程:模板({ {}}语法)—> ast(抽象语法树)—> f(x)(渲染函数)—>虚拟Dom—>DOM(diff算法)
小知识:vue的前两步一般由vue-template-compiler执行,也就是.vue文件可以有模板,非.vue文件不行,因为我们默认装的vue是runtime-only的。也就是只走 f(x) —> 虚拟dom —> DOM 这三步