面试题答案
一键面试延迟加载策略
- 基于视口的懒加载:
- 使用
IntersectionObserver
API,它可以异步观察目标元素与其祖先元素或顶级文档视口(viewport)交叉变化情况。对于图片资源,例如在Qwik的组件中,可以这样实现:
import { component$, useTask$ } from '@builder.io/qwik'; export const LazyImage = component$(() => { const loadImage = useTask$(() => { // 这里处理图片加载逻辑,例如创建Image对象并设置src const img = new Image(); img.src = 'your - image - url.jpg'; document.body.appendChild(img); }); return ( <div> <div onIntersect={loadImage} intersectionOptions={{ threshold: 0.1 }} > {/* 占位元素,比如一个loading的占位图 */} </div> </div> ); });
- 对于脚本资源,也可以类似处理。当脚本所在元素进入视口一定比例(通过
threshold
设置)时,开始加载脚本。
- 使用
- 基于路由的延迟加载:
- 在Qwik应用中,当使用路由切换页面时,如果某些资源仅在特定页面使用,可以在路由进入该页面时延迟加载。例如,使用Qwik Router,可以在路由的
enter
钩子函数中触发资源加载。
import { component$, useTask$, RouterContext } from '@builder.io/qwik'; export const PageWithLazyResources = component$(() => { const { route } = useContext$(RouterContext); const loadResources = useTask$(() => { // 加载图片、脚本等资源的逻辑 }); useOnMount$(() => { route.enter$.subscribe(loadResources); }); return ( <div> {/* 页面内容 */} </div> ); });
- 在Qwik应用中,当使用路由切换页面时,如果某些资源仅在特定页面使用,可以在路由进入该页面时延迟加载。例如,使用Qwik Router,可以在路由的
处理资源依赖关系
- 顺序加载:
- 如果资源A依赖于资源B,例如一个JavaScript脚本依赖于另一个基础库脚本,先确保加载基础库脚本。可以使用
Promise
来管理加载顺序。
const loadScript = (src) => { return new Promise((resolve, reject) => { const script = document.createElement('script'); script.src = src; script.onload = resolve; script.onerror = reject; document.head.appendChild(script); }); }; const loadDependentScripts = async () => { await loadScript('base - library.js'); await loadScript('dependent - script.js'); };
- 如果资源A依赖于资源B,例如一个JavaScript脚本依赖于另一个基础库脚本,先确保加载基础库脚本。可以使用
- 依赖图管理:
- 对于复杂的资源依赖关系,可以构建一个依赖图。每个资源作为节点,依赖关系作为边。可以使用拓扑排序算法(如Kahn算法)来确定资源的加载顺序。例如:
const resourceDependencies = { 'image1.jpg': [], 'script1.js': ['image1.jpg'], 'script2.js': ['script1.js'] }; const topologicalSort = (graph) => { const inDegree = {}; const result = []; const queue = []; for (const node in graph) { inDegree[node] = 0; } for (const node in graph) { for (const neighbor of graph[node]) { inDegree[neighbor] = (inDegree[neighbor] || 0) + 1; } } for (const node in inDegree) { if (inDegree[node] === 0) { queue.push(node); } } while (queue.length > 0) { const node = queue.shift(); result.push(node); for (const neighbor of graph[node]) { inDegree[neighbor]--; if (inDegree[neighbor] === 0) { queue.push(neighbor); } } } return result; }; const loadOrder = topologicalSort(resourceDependencies); // 按照loadOrder的顺序加载资源