面试题答案
一键面试实现思路
- 服务端渲染(SSR)兼容:在SSR场景下,由于服务器没有浏览器环境,不能直接使用浏览器特有的API(如
IntersectionObserver
)。因此需要采用一些特殊策略来确保图片在服务端渲染时能够正确处理。可以在服务端渲染时根据页面布局和图片位置,提前判断哪些图片需要加载,而不是依赖浏览器的视口相关事件。 - 客户端渲染处理:在客户端,使用
IntersectionObserver
来实现传统的图片懒加载逻辑。当图片进入视口时才加载图片资源,以节省带宽和提高页面性能。 - 统一管理:为了确保服务端和客户端渲染都能正常工作,需要统一图片的管理和配置。可以通过自定义指令或者插件来实现这一功能,使得在不同环境下都能正确处理图片懒加载。
关键代码点
- 自定义指令(推荐方式):
- 创建自定义指令:
import Vue from 'vue';
Vue.directive('lazyload', {
inserted: function (el, binding) {
if (process.server) {
// 服务端渲染处理
// 这里可以根据页面布局和el的位置等信息,提前加载图片
// 例如,如果是首屏可见区域的图片,可以直接设置src
if (isInFirstScreen(el)) {
el.src = binding.value;
}
} else {
// 客户端渲染处理
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
el.src = binding.value;
observer.unobserve(el);
}
});
});
observer.observe(el);
}
}
});
function isInFirstScreen(el) {
// 简单示例:判断元素是否在首屏,实际需要根据页面布局精确计算
const rect = el.getBoundingClientRect();
return rect.top >= 0 && rect.bottom <= window.innerHeight;
}
- 在模板中使用:
<template>
<div>
<img v-lazyload="imageUrl" alt="Lazy Loaded Image">
</div>
</template>
<script>
export default {
data() {
return {
imageUrl: 'your-image-url.jpg'
};
}
};
</script>
- 使用插件:
- 安装并引入插件:例如
vue - lazyload
插件。
- 安装并引入插件:例如
npm install vue - lazyload
import Vue from 'vue';
import VueLazyload from 'vue - lazyload';
Vue.use(VueLazyload, {
preLoad: 1.3,
error: 'default - error - image.jpg',
loading: 'default - loading - image.jpg',
attempt: 1,
listenEvents: ['scroll', 'wheel', 'mousewheel', 'resize', 'animationend', 'transitionend'],
observer: true,
observerOptions: {
root: null,
rootMargin: '0px',
threshold: 0.1
}
});
- 在模板中使用:
<template>
<div>
<img v - lazy="imageUrl" alt="Lazy Loaded Image">
</div>
</template>
<script>
export default {
data() {
return {
imageUrl: 'your - image - url.jpg'
};
}
};
</script>
在使用插件时,vue - lazyload
插件已经对SSR有一定的支持,会在服务端和客户端根据环境进行不同的处理。但在服务端可能还需要根据具体业务场景进一步优化,比如对首屏图片提前加载等操作。