响应式布局中display:none性能影响、按需加载实现及fetch报错排查
关于
display:none的性能影响 - 设为
display:none的元素,浏览器依然会完成DOM解析、关联资源(图片、字体、子元素JS逻辑)的下载流程,仅跳过渲染阶段的重排、重绘操作,不会在页面上展示。 - 性能影响程度和隐藏元素的体积、复杂度直接相关:
- 纯文本、无关联资源的普通元素,基本无性能损耗。
- 包含大量图片、视频、复杂CSS动画的元素,哪怕隐藏也会占用带宽、设备解析资源,移动端、低端设备上会出现明显的加载变慢、流量浪费问题。
- 大量重复的隐藏元素会推高DOM体积,导致JS遍历DOM、绑定事件时的开销上升。
无冗余加载的实现方案
采用移动优先思路时,优先避免把小屏不需要的内容直接写入初始HTML:
- 静态内容场景:复用同一套DOM结构,仅通过媒体查询控制不同尺寸下的渲染状态,不要单独写两套仅展示尺寸不同的重复DOM,减少DOM冗余。
- 动态区块场景:仅在视口宽度满足对应阈值时,通过JS请求加载专属内容,小屏初始页面不加载大屏专属资源。
- 资源优化:对隐藏状态下的图片,不要提前写入
src属性,等需要展示时再赋值加载,避免无效资源下载。
按需加载代码的报错修复
报错原因
报错Cannot set property 'innerHTML' of null的核心是document.querySelector(".containerAnime2")未查询到对应元素,另有多处代码逻辑错误:
- 脚本执行时机过早:DOM未加载完成就执行元素查询,找不到目标容器。
- Fetch返回值处理错误:
fetch返回的是Response对象,并非直接的HTML字符串,需要调用.text()方法提取文本内容。 - 服务端返回格式错误:接口返回了完整HTML文档骨架(包含
<!DOCTYPE html>、<html>标签),直接嵌套进页面会出现冗余节点。 - 视口判断逻辑不准确:用
screen.width判断视口宽度存在误差,该属性返回设备物理分辨率,而非当前浏览器可视区域宽度,窗口缩放、外接显示器场景下会匹配错误。
修复后的代码
- 初始HTML预留空容器,不提前加载冗余内容:
<div class="containerAnime2"></div>
- 调整后的JS逻辑,需放在DOM加载完成后执行:
<script> document.addEventListener('DOMContentLoaded', function() { // 用window.innerWidth获取真实可视区域宽度 const isDesktop = window.innerWidth > 1024; const url = isDesktop ? '/api-test.php' : '/api-test2.php'; fetch(url) .then(res => { if (!res.ok) throw new Error('请求异常'); // 提取返回的HTML文本 return res.text(); }) .then(html => { const container = document.querySelector('.containerAnime2'); // 确认容器存在后再赋值 if (container) container.innerHTML = html; }) .catch(err => console.error(err)); }); </script>
- 服务端接口(
api-test.php)调整为仅返回需要的区块片段,移除完整HTML骨架:
<div class="animeinfoLeft"> <img src="/images/background_animes/<?= $get_anime['url_nome']; ?>.jpg"/> </div> <div class="animeinfoRight"> <p><?= $get_anime['nome']; ?> Todos os Episódios Online</p> <div class="extra"> <span class="elementExtra"><img src="/images/star-icon.png" style="width:16px; height:16px;vertical-align:-1px;"/> <?= $get_anime['nota']; ?></span> <span class="elementExtra"><img src="/images/iconDate.png" style="width:16px; height:16px;vertical-align:-1px;"/> <?= $get_anime['ano']; ?></span> <span class="elementExtra"><?= $episodios_count['0']; ?> Episódio<?= (($episodios_count['0'] > 1) ? 's' : ''); ?></span> </div> <div class="tags"> <?php foreach ($tags_array as $genero) { echo '<a href="/letras/'. $genero .'/"><span class="elementTag">'. $genero .'</span></a>'; } ?> </div> <div class="description"> <p><?= $get_anime['nome']; ?> Todos os Episódios Online, Assistir <?= $get_anime['nome']; ?> Anime Completo, Assistir <?= $get_anime['nome']; ?> Online.<br><br><?= $description; ?></p> </div> <a href="#"> <div class="errorButton"> RELATAR ERRO OU EPISÓDIO NOVO </div> </a> </div>
内容的提问来源于stack exchange,提问作者kanohn
相关产品推荐
相关产品推荐

