记录前端面试八股文
1.事件委托的理解
为什么叫事件委托?它还有一个名字叫事件代理
JavaScript高级程序设计上讲:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
2.重绘和回流的区别
在 HTML 中,每个元素都可以理解成一个盒子,在浏览器解析过程中,会涉及到回流与重绘:
- 回流(reflow):当DOM的结构发生改变或者某个元素的样式发生变化时,浏览器需要重新计算并重新布局(layout)页面中的元素,这个过程就称为回流。回流会导致浏览器重新计算元素的位置和大小,然后重新绘制到屏幕上,是一种相对耗费资源的操作。
- 重绘(repaint):当页面元素的样式(如颜色、背景等)发生变,但并不影响其布局时,浏览器只需要重新绘制(repaint)这些元素,而无需重新计算元素的布局,这个过程称为重绘。重绘的性能开销较小,因只是简单地更新元素的样式。
要了解回流与重绘的产生,首先需要了解浏览器解析渲染机制,如下所示:
浏览器的解析渲染机制可以分为以下几个步骤:
- HTML解析:当浏览器接收到 HTML 文档后,会对其进行解析。解析器会将 HTML 文档按照标签的层次结构转换成一个 DOM 树(文档对象模型)。 DOM 树表示了文档的结构,每个 HTML 标签都对应着 DOM 树中的一个节点。
- CSS解析:浏览器会解析 CSS 样式表,构建 CSSOM (CSS对象模型)。 CSSOM 表示了文档的样式信息,每个 CSS 样式规则都对应着 CSSOM 中的一个对象。
- 渲染树构建:将 DOM 树和 CSSOM 合并构建渲染树(
Render Tree)。渲染树只包含需要显示的元素,隐藏的元素不会包含在渲染树中。渲染树不包含 CSS 中的一些影响布局但不显示的元素,比如:display:none的元素。 - 布局(Layout) :布局阶段确定渲染树中每个节点的精确位置和大小,按照文档流模型进行布局。计算节点的几何属性,比如位置、大小等。
- 绘制(Paint) :根据渲染树的布局信息,将每个节点转换为屏幕上的实际像素,通过绘制进行渲染。
- 栅格化(Rasterization) :将绘制得到的图像划分成图块,然后将每个图块转化成屏幕上的像素。
- 合成(Composition) :将图块按照正确的顺序合并,形成最终的页面图像。
以上步骤并非严格的顺序执行,其中一些步骤可能会并行进行,以提高效率。在渲染过程中,如果发生了样式改变,浏览器会重新执行布局和绘制操作,更新渲染结果。
所以在页面初始渲染阶段,回流不可避免的触发,可以理解成页面一开始是空白的元素,后面添加了新的元素使页面布局发生改变
当我们对 DOM 的修改引发了 DOM 几何尺寸的变化(比如修改元素的宽、高或隐藏元素等)时,浏览器需要重新计算元素的几何属性,然后再将计算的结果绘制出来
当我们对 DOM 的修改导致了样式的变化(color或background-color),却并未影响其几何属性时,浏览器不需重新计算元素的几何属性、直接为该元素绘制新的样式,这里仅仅触发了重绘。
3.vue3如何获取当前组件实例?
通过getCurrentInstance来获取当前组件实例,但不推荐在生产环境使用,仅推荐用于测试和调试目的
4.vue是如何渲染和更新组件的?
Vue组件渲染和更新的过程简单地概况为以下几个步骤:
1.初始化组件实例:在渲染一个组件之前,Vue会创建一个组件实例,并将组件的选项对象进行合并、处理,最终形成一个组件实例的配置对象。
2.渲染组件:Vue将组件实例的配置对象转化为一个渲染函数,并执行该渲染函数,生成一个虚拟DOM树。此时,Vue会对虚拟DOM树进行初次渲染,将组件显示在页面上。
3.监听数据变化:当组件实例中的响应式数据发生变化时,Vue会立即检测到这些变化,并重新计算组件的渲染函数,生成一个新的虚拟DOM树。
4.对比新旧虚拟DOM树:Vue会将新生成的虚拟DOM树和上一次渲染时生成的虚拟DOM树进行比较,找出需要更新的部分。 更新组件:Vue会将需要更新的部分进行精细化地修改,使组件达到更新的效果。如果有需要,Vue会重新渲染整个组件。
延伸:父子组件渲染和更新的顺序
一、加载渲染过程 当Vue实例开始创建时,会按照以下顺序执行生命周期钩子:
父组件的beforeCreate:此时,父组件的实例初始化完成,但还不能访问data和methods。
父组件的created:父组件的实例创建完成,数据监听、计算属性、方法和事件/监听器都已配置完毕。此时可以访问data和methods,但页面还没有渲染出来。
父组件的beforeMount:完成对DOM的初始化,虚拟DOM(在内存中)已生成,但还没有真实的DOM,Vue还没有挂载真实DOM。
子组件的beforeCreate:开始执行子组件的beforeCreate钩子。
子组件的created:子组件的实例创建完成。
子组件的beforeMount:子组件开始准备挂载。
子组件的mounted:子组件挂载真实DOM完成。
父组件的mounted:在所有子组件都挂载完成后,父组件才会执行mounted钩子。这意味着父组件的mounted钩子会在所有子组件的mounted钩子之后执行。
二、更新过程 当组件的数据发生变化时,会触发更新过程。对于父子组件的更新,执行顺序如下:
父组件的beforeUpdate:在父组件的虚拟DOM打补丁之前调用。
子组件的beforeUpdate:如果子组件依赖于父组件的数据,那么子组件也会在执行更新前调用beforeUpdate钩子。
子组件的updated:子组件的DOM已经更新,数据也是最新的。
父组件的updated:在所有子组件的updated钩子之后,父组件的updated钩子才会执行。
三、销毁过程 当Vue实例销毁时,会执行以下生命周期钩子:
父组件的beforeDestroy:在Vue实例销毁之前调用。在这一步,实例仍然完全可用。
子组件的beforeDestroy:子组件也会在其销毁前调用beforeDestroy钩子。
子组件的destroyed:Vue实例销毁后调用。此时,所有的指令都已解绑,所有的事件监听器被移除,所有的子实例也都被销毁。
父组件的destroyed:在所有子组件都销毁后,父组件的destroyed钩子才会执行。
总结 父子组件生命周期的执行顺序可以概括为:
| 生命周期阶段 | 父子组件执行顺序 |
|---|---|
| 加载渲染 | 父beforeCreate → 父created → 父beforeMount → 子beforeCreate → 子created → 子beforeMount → 子mounted → 父mounted |
| 更新过程 | 父beforeUpdate → 子beforeUpdate → 子updated → 父updated |
| 销毁过程 | 父beforeDestroy → 子beforeDestroy → 子destroyed → 父destroyed |