【每日前端面经】2024-03-10
欢迎订阅我的前端面经专栏: 每日前端面经
本期题目来源: 牛客
回流与重绘
-
重绘:当一个元素的外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,叫做重绘
-
回流:当DOM的变化影响了元素的几何信息(元素的的位置和尺寸大小),浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置
- 页面初始渲染,这是开销最大的一次回流
- 添加/删除可见的 DOM 元素
- 改变元素位置
- 改变元素尺寸,比如边距、填充、边框、宽度和高度等
- 改变元素内容,比如文字数量,图片大小等
- 改变元素字体大小
- 改变浏览器窗口尺寸,比如 resize 事件发生时
- 激活 CSS 伪类(例如::hover)
- 设置 style 属性的值,因为通过设置 style 属性改变结点样式的话,每一次设置都会触发一次 reflow
- 查询某些属性或调用某些计算方法:offsetWidth、offsetHeight等,除此之外,当我们调用 getComputedStyle 方法,或者IE里的 currentStyle 时,也会触发回流,原理是一样的,都为求一个即时性和准确性
如何避免回流
减少范围
- 尽可能在低层级的DOM节点上,而不是像上述全局范围的示例代码一样,如果你要改变p的样式,class就不要加在div上,通过父元素去影响子元素不好
- 不要使用 table 布局,可能很小的一个小改动会造成整个 table 的重新布局。那么在不得已使用table的场合,可以设置table-layout:auto;或者是table-layout:fixed这样可以让table一行一行的渲染,这种做法也是为了限制reflow的影响范围
减少次数
- 样式集中改变: 不要频繁的操作样式,对于一个静态页面来说,明智且可维护的做法是更改类名而不是修改样式,对于动态改变的样式来说,相较每次微小修改都直接触及元素,更好的办法是统一在 cssText 变量中编辑。虽然现在大部分现代浏览器都会有 Flush 队列进行渲染队列优化,但是有些老版本的浏览器比如IE6的效率依然低下
- 分离读写操作:DOM 的多个读操作(或多个写操作),应该放在一起。不要两个读操作之间,加入一个写操作
- 将 DOM 离线
- 使用 display: none
- 通过 documentFragment 创建文档碎片在添加进文档中
- 复制节点 -> 操作副本 -> 替换
- 使用 absolute / fixed 脱离文档流:使用绝对定位会使的该元素单独成为渲染树中 body 的一个子元素,回流开销比较小,不会对其它节点造成太多影响。当你在这些节点上放置这个元素时,一些其它在这个区域内的节点可能需要重绘,但是不需要回流
- 优化动画
Vue 组件通信
- Props / 组件属性
- Custom Events / 自定义属性
- Event Bus / 事件总线
- VueX / 状态管理
- Provide & Inject / 依赖注入
- Ref & Reactive
- 全局事件
- useAttrs
- Pinia
- Slots / 插槽
- v-model / 双向绑定
父子组件生命周期
- 父beforeCreate
- 父created
- 父beforeMount
- 子beforeCreate
- 子created
- 子beforeMount
- 子mounted
- 父mounted
- 父beforeUpdate
- 子beforeUpdate
- 子updated
- 父updated
- 父beforeDestroy
- 子beforeDestroy
- 子destroyed
- 父destroyed
new Set() 方法的作用
Set 是 es6 新增的数据结构,似于数组,但它的一大特性就是所有元素都是唯一的,没有重复的值,我们一般称为集合。Set本身是一个构造函数,用来生成 Set 数据结构
super 关键字
super 关键字用于访问对象字面量或类的原型([[Prototype]])上的属性,或调用父类的构造函数
- 在派生类的构造函数体中(使用 extends),super 关键字可以作为“函数调用”(super(…args))出现,它必须在使用 this 关键字之前和构造函数返回之前被调用。它调用父类的构造函数并绑定父类的公共字段,之后派生类的构造函数可以进一步访问和修改 this
class Polygon {
constructor(height, width) {
this.name = "Rectangle";
this.height = height;
this.width = width;
}
sayName() {
console.log("Hi, I am a ", this.name + ".");
}
get area() {
return this.height * this.width;
}
set area(value) {
this._area = value;
}
}
class Square extends Polygon {
constructor(length) {
this.height; // ReferenceError,super 需要先被调用!
// 这里,它调用父类的构造函数并传入 length
// 作为 Polygon 的 height, width
super(length, length);
// 注意:在派生的类中,在你可以使用 'this' 之前,必须先调用 super()。
// 现在可以使用 'this' 了,忽略 'this' 将导致引用错误(ReferenceError)
this.name = "Square";
}
}
- 属性查询形式可以用来访问一个对象字面或类的 [[Prototype]] 的方法和属性。在一个类的主体中,super 的引用可以是父类的构造函数本身,也可以是构造函数的 prototype,这取决于执行环境是实例创建还是类的初始化
class Rectangle {
static logNbSides() {
return "I have 4 sides";
}
}
class Square extends Rectangle {
static logDescription() {
return `${super.logNbSides()} which are all equal`;
}
}
Square.logDescription();
Webpack 构建流程
- 初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数
- 开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译; 确定入口:根据配置中的 entry 找出所有的入口文件
- 编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行编译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理
- 完成模块编译:在经过第 4 步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会
- 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统
加载 chunk 的原理
Chunk 不同于 entry、 output、module 这样的概念,它们对应着 Webpack 配置对象中的一个字段,Chunk 没有单独的配置字段,但却出现在 CommonsChunkPlugin(Webpack3 以前)、optimization.splitChunks(Webpack4 以后)这样的名称之中
Webpack 可以看做是模块打包器,我们编写的任何文件,对于 Webpack 来说,都是一个个模块。所以 Webpack 的配置文件,有一个 module 字段,module 下有一个 rules 字段,rules 下有就是处理模块的规则,配置哪类的模块,交由哪类 loader 来处理
Chunk 是 Webpack 打包过程中,一堆 Module 的集合。我们知道 Webpack 的打包是从一个入口文件开始,也可以说是入口模块,入口模块引用这其他模块,模块再引用模块。Webpack 通过引用关系逐个打包模块,这些 Module 就形成了一个 Chunk
常见的状态码
分类 | 描述 | 举例 |
---|---|---|
1** | 信息,服务器收到请求,需要请求者继续执行操作 | |
2** | 成功,操作被成功接收并处理 | 200: 请求成功; |
3** | 重定向,需要进一步的操作以完成请求 | 301: 资源已经被永久移动; |
4** | 客户端错误,请求包含语法错误或无法完成请求 | 403: 拒绝执行此请求; 404: 无法找到请求的资源; 405: 请求的方法被禁止; |
5** | 服务器错误,服务器在处理请求的过程中发生了错误 | 505: 服务器不支持请求的 HTTP 版本; 500: 服务器内部错误,无法完成请求; |
缓存
基本的网络请求就是三个步骤:请求,处理,响应
前端缓存则可以在请求和响应中进行。在请求步骤中,浏览器也可以通过存储结果的方式直接使用资源,直接省去了发送请求;而响应步骤需要浏览器和服务器共同配合,通过减少响应内容来缩短传输时间
重排(reflow)和重绘(repaint)
Vue——父子组件的生命周期(执行顺序)
MDN
一文说清 Webpack 的整体构建流程
理解 Webpack 中的 Chunk
一文读懂前端缓存
新人发文,礼貌求关❤️