今天测试分配了一个比较奇怪的问题,在单页面应用中,反复点击“上一步”和“下一步”按钮时,界面表现出逐渐变得卡顿。为分析这一问题,我用Chrome的性能监控工具进行了浏览器性能录制。结果显示,每次点击“上一步”按钮时,JavaScript堆内存(JS Heap)和事件监听器(listener)的数量显著增加,并且随着点击次数的增加,这种增长趋势变得越来越明显,所需的时间也逐渐延长。如图所示:
于是我开始查找代码里的监听器,发现了这个监听代码
history.listen((_,type)=>{
if (type==='POP'){
setMchInfo({...mchInfo})
}
})
这是一个用于监听浏览器历史记录变化的方法。当历史记录发生变化时,传递给listen方法的回调函数会被调用。
而我点击上一步时,会触发这么一个函数
const prevStep = () => {
history.go(-1);
};
而这个函数就会触发history.listen,从而增加监听器数量
这样,我们需要在监听器用完的时候直接移除添加的监听器
useEffect(() => {
const unlisten = history.listen((_, type) => {
if (type === 'POP') {
setMchInfo({ ...mchInfo });
}
});
return () => {
unlisten();
};
}, [history]);
unlisten是history.listen返回的函数,用于移除之前添加的监听器,useEffect钩子的清理函数机制保证了在history变化时,只有旧的监听器会被移除,而新的监听器会在清理之后重新添加,避免内存泄漏。
重试了一次,问题完美解决。