Material-UI中makeStyles定义在组件内外的性能差异对比
关于Material-UI中useStyles定义位置的解答
将
useStyles定义在函数组件外部是官方推荐的标准最优写法,两种写法在实际运行中存在明确的性能差异,不推荐将makeStyles调用写在组件内部。
两种写法的核心差异
- 执行时机与重复开销不同
makeStyles本身是一个工厂函数,作用是接收样式规则配置,生成对应的样式hook、完成CSS规则序列化与DOM注入逻辑,这个过程只需要执行1次。
如果把makeStyles调用写在组件内部,每次组件重渲染都会重新执行makeStyles生成一个全新的hook实例,每次新实例首次调用时都会重复走样式ID生成、CSS规则计算、DOM样式插入的流程,哪怕写的样式内容完全没有变化。高频重渲染场景下,这部分重复计算会带来不必要的CPU开销,还可能在DOM中堆积大量冗余的<style>标签,增加浏览器样式计算的负担。 - 内存占用与稳定性不同
定义在组件外部的useStyles是模块级单例,不管组件被实例化多少次、重渲染多少次,只会生成一份CSS规则,不会产生冗余的实例和DOM节点,内存占用更低,也不会出现样式重复注入导致的优先级错乱问题。
写在组件内部的写法每次重渲染都会生成新的hook实例,旧实例关联的样式如果没有被及时回收,会造成内存泄漏,极端场景下会出现样式覆盖异常的偶现bug。
动态样式场景的正确处理方式
如果需要用到组件props、组件内部状态生成动态样式,不需要把makeStyles挪到组件内部,直接把动态值作为参数传给useStyles即可,参考示例:
import React, { useState } from 'react'; import { makeStyles } from '@material-ui/core'; // useStyles始终定义在组件外部 const useStyles = makeStyles(theme => ({ root: { display: 'flex', alignItems: 'center', justifyContent: 'center', // 通过函数形参拿到传入的动态值 backgroundColor: props => props.highlight ? theme.palette.primary.main : 'transparent' } })); const Welcome = ({highlight}) => { const [isAuthenticated, setIsAuthenticated] = useState(true); const classes = useStyles({ highlight }); // 传入动态参数 return ( <div className={classes.root}> ... </div> ) }
性能差异的实际感知
如果组件仅在页面加载时渲染1次、几乎不触发重渲染,两种写法的差异很难被用户感知;但如果组件属于高频重渲染类型(比如长列表项、实时输入关联组件、拖拽交互组件),把makeStyles写在内部带来的重复开销会明显拉长渲染耗时,甚至造成页面卡顿。
内容的提问来源于stack exchange,提问作者hahahaflying
相关产品推荐
相关产品推荐

