1.项目相关,遇到的难点
2.浏览器的渲染原理和过程
[[前端面试常见题-网络和工程化篇]]
3.重排和重绘的概念,分别在什么时候触发
[[前端面试常见题-网络和工程化篇]]
4.为什么transform不会导致重排
简单来说,transform
不会导致重排(Reflow),因为它作用于浏览器渲染流程中一个独立的阶段——合成(Composite)。
浏览器的渲染有这么几个步骤:
- Style (样式计算):浏览器计算出每个 DOM 元素最终的 CSS 样式。
- Layout (布局/重排 - Reflow):浏览器根据元素的样式计算出它在屏幕上的确切位置和大小(几何信息)。页面上任何一个元素的几何属性(如
width
,height
,left
,top
,margin
)发生变化,都可能影响其他元素的位置,导致浏览器需要重新计算整个页面的布局。这个过程开销非常大,是性能的主要瓶颈。 - Paint (绘制/重绘 - Repaint):浏览器知道了元素的位置和大小后,会将元素的视觉内容(如颜色、背景、边框等)绘制到一个个“图层”(Layers)上。
- Composite (合成):浏览器将所有绘制好的图层按照正确的顺序合并,最终显示在屏幕上。
transform
的聪明之处在于,它跳过了 Layout 和 Paint 这两个最昂贵的步骤。
- 图层提升 (Layer Promotion):当浏览器遇到某些特定的 CSS 属性时,比如
transform
或opacity
,会将其放到一个新的合成层上 - GPU 加速:这个新的合成层会被直接交给 GPU 来处理。
- 跳过重排和重绘
5.强制重排和强制重绘的概念
强制重排是指,JavaScript 代码在修改了 DOM 样式之后,没有等待浏览器异步地批量处理,而是立即请求读取某个需要依赖最新布局信息的属性。
读取以下任何一个属性或调用任何一个方法,浏览器都必须进行强制重排,以返回精确的值:
elem.offsetHeight
,elem.offsetWidth
,elem.offsetLeft
,elem.offsetTop
elem.clientHeight
,elem.clientWidth
,elem.clientLeft
,elem.clientTop
elem.scrollHeight
,elem.scrollWidth
,elem.scrollLeft
,elem.scrollTop
elem.getBoundingClientRect()
getComputedStyle()
强制重排可能导致页面卡顿和掉帧,为了避免强制重排,需要遵循 读写分离 的原则。
强制重绘是指当你修改了非几何类的样式(如 color
, background-color
, box-shadow
),然后立即通过 getComputedStyle()
等方法去读取这些视觉样式时,浏览器可能需要强制执行“绘制(Paint)”过程来给你一个准确的计算值。
6.事件循环和raf,raf在浏览器渲染的哪个阶段
重排之前执行;
更精确地说,它位于浏览器处理一帧画面的起始阶段,在执行 Style (样式计算) 和 Layout (布局) 之前。
在一帧时间里,浏览器大致会按以下顺序执行任务:
- 处理输入事件 (Input Events):响应用户的点击、滚动、鼠标移动等。
- 执行 JavaScript (Timers, Events):执行
setTimeout
,setInterval
的回调,以及其他事件回调。 requestAnimationFrame
(RAF) 回调:这是关键点! 浏览器会执行所有通过requestAnimationFrame
注册的回调函数。这是官方推荐的、进行所有视觉变更(DOM 操作、样式修改)的最佳时机。- 样式计算 (Style):根据你在 RAF 回调中修改的样式,浏览器重新计算每个元素的最终样式。
- 布局 (Layout / Reflow):如果几何属性(如宽度、高度、位置)发生变化,浏览器会重新计算布局。
- 绘制 (Paint / Repaint):将元素的视觉内容绘制到图层上。
- 合成 (Composite):将所有图层合并,最终显示在屏幕上。
7.http协议,http2的特点,多路复用的作用
8.听说过雪碧图吗?为什么不用了?如果带宽无限,可以有无限个TCP连接,多路复用还有必要吗?
PS:浏览器最多支持6个TCP连接
9.Vue和React的区别?为什么Vue中没有类似于useMemo之类的缓存相关的钩子
10.对于一个搜索框的联想来说,除了防抖的操作,React官方提供了什么钩子?
useTransition
https://zh-hans.react.dev/reference/react/useTransition
import React, { useState, useTransition } from 'react';
// 假设我们有一个显示联想结果的组件
function SuggestionList({ query }) {
// ... 在这里根据 query 获取并显示数据 ...
return <ul>...</ul>;
}
function SearchBox() {
const [inputValue, setInputValue] = useState(''); // 用于输入框的紧急状态
const [searchQuery, setSearchQuery] = useState(''); // 用于触发搜索的延迟状态
const [isPending, startTransition] = useTransition();
const handleChange = (e) => {
// 1. 紧急更新:立即更新输入框的值
setInputValue(e.target.value);
// 2. 非紧急更新:用 startTransition 包裹
// React 会在浏览器空闲时执行这里面的更新,不会阻塞UI
startTransition(() => {
setSearchQuery(e.target.value);
});
};
return (
<div>
<input
type="text"
value={inputValue}
onChange={handleChange}
placeholder="Search..."
/>
{isPending && <div>Loading...</div>}
<SuggestionList query={searchQuery} />
</div>
);
}
11.读代码:setState的更新,React的事件委托机制
12.手撕:单括号匹配(O(1)空间复杂度),多括号匹配,多括号匹配并返回最近一个不匹配的index