在现代网页开发中,尤其是在使用 Vue 和 React 等前端框架时,性能优化依然是提升用户体验的关键。虽然这些框架通过虚拟 DOM 等技术简化了与 DOM 的交互,但重绘(Repaint)和回流(Reflow)的概念依然存在,并且仍然影响着性能。今天我就来重新巩固下这2个概念。
什么是重绘?
重绘是指当元素的外观发生变化(如颜色、背景),但不涉及布局的变化,浏览器需要重新渲染该元素。虽然重绘相对轻量,但频繁的重绘仍会影响应用性能,我们当然是希望越少越好。
什么是回流?
回流是指当元素的尺寸或几何属性发生变化时,浏览器需要重新计算并更新整个页面的布局。这一过程通常比重绘消耗更多资源,尤其是在复杂的应用中,所以我们要避免多余的回流。
为什么在框架中也需要关注重绘与回流?
即使在使用 Vue 和 React 等框架时,重绘与回流仍然存在。例如,当组件的状态变化导致重新渲染时,框架会触发 DOM 的更新,从而可能引发重绘或回流。因此,理解这些概念有助于我们写出更高性能的组件。
在 Vue 和 React 中的优化策略
1. 善用计算属性和 Memoization
在 Vue 和 React 中,通过计算属性computed
或使用 useMemo
钩子,可以有效减少不必要的渲染和优化性能。
示例:Vue 计算属性
1 | // 具有缓存性质,他只有当监听属性发生变化的时候,才会触发 |
示例:React useMemo
1 | const filteredItems = useMemo(() => { |
2. 合理使用 key
在列表渲染中,合理使用 key
属性可以帮助框架识别哪些元素需要更新,从而减少重绘和回流。
示例:
1 | {items.map(item => ( |
3. 控制组件的更新
通过 shouldComponentUpdate
(在类组件中)或 React.memo
(在函数组件中),可以有效控制组件何时需要更新,从而避免不必要的重绘。
示例:React.memo
1 | const MyComponent = React.memo(({ item }) => { |
4. 使用事件节流和防抖
在处理频繁事件时,如窗口 resize 或滚动,使用节流和防抖技术可以减少频繁的重绘和回流。
示例:使用 lodash 的 debounce
1 | const handleResize = debounce(() => { |
5. 按需加载
在大型应用中,按需加载组件可以显著提高初始渲染性能,并减少不必要的回流。React 提供了 React.lazy
和 Suspense
来实现这一功能。
示例:
1 | const LazyComponent = React.lazy(() => import('./LazyComponent')); |
回流必定发生重绘,但是重绘不一样发生回流,回流的性能开销也比重绘大。
最后了解下引起回流和重绘的属性。
1 | 常见引起重绘的属性 |
Ok,回流和重绘我们基本了解了。