资源按需加载的核心是“用时再载”,通过监听滚动判断元素是否进入可视区来触发加载,分为图片(IntersectionObserver)、组件(动态导入)和HTML片段(fetch注入)三类实现,兼顾性能、兼容性与用户体验。

资源按需加载的核心是“用时再载”,不是一上来就把所有图片和组件全拉下来。对图片和组件做滚动加载,本质就是监听用户滚动行为,判断目标是否进入可视区域,再触发加载。实现方式分原生、框架内、构建工具三类,关键在时机控制与资源管理。
图片滚动加载:用 IntersectionObserver 最省心
现代浏览器推荐用 IntersectionObserver 替代频繁监听 scroll 事件,性能好、写法简洁、自动处理边界情况:
- 给 img 标签加
data-src存真实地址,src先设为占位图或空 - 创建观察器,监听所有带
data-src的图片 - 当
entry.isIntersecting为 true,把data-src赋给src,并移除data-src防重复加载 - 加载完成后调用
observer.unobserve(img)停止监听该元素
兼容性注意:IE 不支持,需引入 polyfill;如需兼容老版本,可用 getBoundingClientRect() + 节流 scroll 监听替代,但代码更重、易出错。
Vue/React 组件滚动加载:靠动态导入 + 状态驱动
组件不是图片,不能只换 src —— 它包含逻辑、样式、生命周期。滚动加载组件,实际是“滚动触发动态 import(),再挂载对应模块”:
-
Vue:用异步组件语法
defineAsyncComponent(() => import('./Chart.vue'))或路由级const Page = () => import('./About.vue'),配合v-if或keep-alive控制渲染时机 -
React:用
React.lazy()包裹 import,搭配<Suspense fallback>处理加载中状态 - 滚动到底部时(如
scrollTop + clientHeight >= scrollHeight),更新组件列表数据或切换异步组件标识,触发加载
注意:组件本身不“懒”,是它的 JS chunk 懒;构建工具(Vite/Webpack)会自动拆包,无需手动切 HTML 文件。
HTML 片段按需注入:适合静态内容块,慎用脚本
如果只是加载一段不含交互的 HTML(比如帮助文档、协议弹窗),可 fetch 获取纯 HTML 字符串后插入 DOM:
- 服务端返回无外壳结构,例如:
<div class="notice"><p>条款已更新</p></div> - 前端用
fetch('/terms').then(r => r.text()).then(html => el.innerHTML = html) - ⚠️ 内联
<script>不会执行,<img data-src>也不会自动加载,需额外遍历解析 - 若必须执行脚本,仅限完全可信源,且要用
DOMParser解析后手动创建 script 标签注入(避免 eval)
补充技巧:提升体验与健壮性
滚动加载不只是“能动”,还要“稳而顺”:
- 加 loading 占位骨架屏(skeleton),避免白块闪动
- 预加载临界区域外 1–2 个元素(如
rootMargin: '200px'),减少滚动停顿感 - 图片加载失败时显示 fallback 图或错误提示,避免空白断裂
- 组件加载失败要捕获异常,降级为提示或默认内容,不崩整个页面


















