使用技术
- Intersection Observer API:用于实现图片的懒加载。它可以异步观察目标元素与其祖先元素或视口的交集变化情况。在Vue项目中,可以通过指令(directive)的方式使用它。
- Vue.js:利用Vue的响应式系统、指令以及组件化特性来管理图片的状态和交互。
- Lodash:在处理复杂逻辑时,如防抖、节流等场景下可能会用到,以优化性能。
数据结构
- 商品数据结构:
{
id: '商品唯一标识',
name: '商品名称',
thumbImage: '缩略图地址',
highDefImage: '高清图地址',
panoramaImage: '全景图地址',
seoImages: ['SEO预加载图片地址1', 'SEO预加载图片地址2']
}
- 图片状态数据结构:
{
isLoaded: false, // 图片是否已加载
isHovered: false, // 鼠标是否悬停在图片上
isClicked: false // 图片是否被点击
}
逻辑处理
- 图片懒加载逻辑:
- 创建一个Vue指令,例如
v-lazyload
。
- 在指令的
bind
钩子函数中,使用IntersectionObserver
观察图片元素。
- 当图片进入视口时(即
IntersectionObserver
的回调触发且intersectionRatio > 0
),根据当前图片状态(是否悬停、是否点击等)加载相应规格的图片。
Vue.directive('lazyload', {
bind(el, binding) {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const { isHovered, isClicked } = binding.value;
let imgUrl;
if (isClicked) {
imgUrl = binding.value.highDefImage;
} else if (isHovered) {
imgUrl = binding.value.highDefImage;
} else {
imgUrl = binding.value.thumbImage;
}
el.src = imgUrl;
observer.unobserve(el);
}
});
});
observer.observe(el);
}
});
- 根据用户操作切换图片逻辑:
- 在图片组件中,绑定
mouseenter
和mouseleave
事件,分别用于设置isHovered
为true
和false
。
- 绑定
click
事件,设置isClicked
为true
。根据这些状态的变化,重新触发图片加载逻辑(可以通过重新设置v - lazyload
指令的值来实现)。
<template>
<img v - lazyload="imageData" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave" @click="handleClick" />
</template>
<script>
export default {
data() {
return {
imageData: {
isLoaded: false,
isHovered: false,
isClicked: false,
thumbImage: '...',
highDefImage: '...',
panoramaImage: '...',
seoImages: ['...']
}
};
},
methods: {
handleMouseEnter() {
this.imageData.isHovered = true;
},
handleMouseLeave() {
this.imageData.isHovered = false;
},
handleClick() {
this.imageData.isClicked = true;
}
}
};
</script>
- SEO图片预加载逻辑:
- 在组件的
created
钩子函数中,遍历seoImages
数组,创建Image
对象并设置其src
属性,实现预加载。
export default {
data() {
return {
imageData: {
// 图片数据结构
seoImages: ['...']
}
};
},
created() {
this.imageData.seoImages.forEach(url => {
const img = new Image();
img.src = url;
});
}
};