响应式导航栏两种useLayoutEffect实现方案哪种效率更高?
两种实现方案对比结论
优先选择第二种单useLayoutEffect实现,第一种拆分写法存在明显缺陷,具体分析如下:
- 第一种拆分实现的核心问题:
- 共享的
breakWidth变量定义在两个effect外层,属于模块级变量,当组件多次实例化时会出现多实例状态互相污染的问题,逻辑稳定性差 - 同一个resize事件绑定了两个独立的节流监听器,不仅有额外的性能开销,还可能因两个回调执行顺序不确定导致
hasSpace状态更新冲突 - 关联逻辑拆分到两个独立的effect中,后续维护需要来回跳转查看上下文,可读性差
- 共享的
- 第二种合并实现的优势:
breakWidth封装在effect内部,属于单次组件实例的私有变量,不会出现多实例污染问题- 折叠、恢复逻辑聚合在同一个上下文,可读性、可维护性更高
- 事件绑定和清理逻辑集中管理,不会出现漏清理事件的问题
另外还可以对第二种方案做进一步优化,将两个判断逻辑合并为同一个回调,只需要绑定一次resize事件,简化代码的同时进一步降低性能开销:
useLayoutEffect(() => { let breakWidth; const checkNavStatus = () => { const headerWidth = headerRef.current.clientWidth; // 先判断是否满足恢复条件 if (breakWidth && headerWidth > breakWidth) { setHasSpace(true); } // 再判断是否需要折叠导航 const navOverflow = rightNavRef.current.clientWidth < rightNavRef.current.scrollWidth; if (navOverflow) { setHasSpace(false); breakWidth = headerWidth; } }; checkNavStatus(); const throttledCheck = throttle(checkNavStatus, 50); window.addEventListener('resize', throttledCheck); return () => { window.removeEventListener('resize', throttledCheck); }; }, []);
内容的提问来源于stack exchange,提问作者JPM
相关产品推荐
相关产品推荐

