本文打算# 介绍几个React项目中提高性能的方法,先说一些不常见的给大家尝尝鲜,最后再补充几个常见的,保证知识点的完整性。
1. 使用Web Workers处理复杂计算
在复杂应用中,某些计算密集型任务可能会阻塞主线程,导致界面卡顿。通过Web Workers,你可以将这部分任务移到后台线程执行,从而提高应用的响应性。
javascript
// 创建一个新的Worker
const myWorker = new Worker('worker.js');
myWorker.onmessage = function(e) {
console.log('Message received from worker', e.data);
};
myWorker.postMessage('Hello');
javascript
// worker.js
onmessage = function(e) {
console.log('Message received from main script');
const result = e.data; // 执行一些任务
postMessage(result);
};
2. 利用CSS Containment减少重绘和回流
CSS Containment属性可以让开发者明确地告诉浏览器某个元素的布局、样式或尺寸是独立于文档流的其他部分。这可以帮助浏览器优化渲染性能,减少不必要的重绘和回流。
css
.container {
contain: layout style paint;
}
3. 使用Intersection Observer API懒加载图片和组件
Intersection Observer API提供了一种异步检测目标元素与其祖先或视口交叉状态变化的方法。与传统的滚动监听相比,它更高效,可以用于懒加载图片或组件。
javascript
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// 加载图片或显示组件
entry.target.src = entry.target.dataset.src;
}
});
});
document.querySelectorAll('img.lazy').forEach(img => observer.observe(img));
4. 使用requestIdleCallback优化低优先级任务
requestIdleCallback
允许你在浏览器空闲时运行低优先级任务,而不会影响关键渲染路径。这对于性能优化尤其有用。
javascript
requestIdleCallback(myNonEssentialFunction, { timeout: 2000 });
function myNonEssentialFunction(deadline) {
while (deadline.timeRemaining() > 0 && tasks.length > 0) {
doNextTask();
}
}
5. 利用Reselect库优化Redux状态选择
如果你在使用Redux,Reselect库可以帮你创建可记忆的(memoized)选择器。这意味着当状态没有变化时,选择器不会重新计算,从而节省了不必要的计算资源。
javascript
import { createSelector } from 'reselect';
const getVisibilityFilter = (state) => state.visibilityFilter;
const getTodos = (state) => state.todos;
const getVisibleTodos = createSelector(
[getVisibilityFilter, getTodos],
(visibilityFilter, todos) => {
switch (visibilityFilter) {
case 'SHOW_ALL':
return todos;
// 更多筛选逻辑...
}
}
);
6. 使用React.memo
避免不必要的重新渲染
React.memo
是一个高阶组件,它可以帮助我们避免在props没有改变时重新渲染组件,从而提高性能。
jsx
const MyComponent = React.memo(function MyComponent(props) {
// 你的组件实现
});
7. 懒加载组件
React支持通过React.lazy
和Suspense
来实现组件的懒加载,这可以减少应用的初始加载时间。
jsx
import React, { Suspense } from 'react';
const LazyComponent = React.lazy(() => import('./LazyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}
8. 使用shouldComponentUpdate
或React.PureComponent
在类组件中,可以通过实现shouldComponentUpdate
方法来避免不必要的更新。此外,继承自React.PureComponent
的组件会自动进行浅比较来避免不必要的渲染。
jsx
class MyComponent extends React.PureComponent {
render() {
return <div>{this.props.name}</div>;
}
}
9. 使用useMemo
和useCallback
钩子
在函数组件中,useMemo
和useCallback
钩子可以帮助我们缓存计算结果和函数,避免在每次渲染时都重新计算或创建。
jsx
import React, { useMemo, useCallback } from 'react';
function MyComponent(props) {
const memoizedValue = useMemo(() => computeExpensiveValue(props.a, props.b), [props.a, props.b]);
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
return <div>{memoizedValue}</div>;
}
10. 分割代码
利用Webpack等打包工具提供的代码分割(Code Splitting)功能,可以将代码拆分成小的块,然后按需加载,这样可以显著减少应用的初始加载时间。
javascript
// 使用动态导入语法实现代码分割
import('path/to/your/module').then((module) => {
// 使用module
});
11. 优化大列表渲染
对于渲染大量数据的列表,可以使用react-window
或react-virtualized
这样的库来实现虚拟滚动,只渲染可视区域内的元素。
jsx
import { FixedSizeList as List } from 'react-window';
const Row = ({ index, style }) => (
<div style={style}>Row {index}</div>
);
function MyList() {
return (
<List
height={150}
itemCount={1000}
itemSize={35}
width={300}
>
{Row}
</List>
);
}
是不是感觉还可以,感觉还可以就点个赞。感觉不太行就在评论区打出
js
我觉得不太行
谢谢!