除了 Vue 内置的一系列指令 (比如 v-model
或 v-show
) 之外,Vue 还允许你注册 自定义的指令
一个自定义指令由一个包含类似组件生命周期钩子的对象来定义。自定义指令必须以 v-xxx 开头 钩子函数会接收到指令所绑定元素作为其参数。以下实现使用自定义指令实现图片懒加载效果:
javascript中有个api可以获取元素是否在可视区 使用 new IntersectionObserver()话不多说看代码:
<template>
<div id="app">
<div class="img">
<img v-lazy="item" alt="" v-for="(item, index) in images" :key="index">
</div>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
images: [
{ url: require("./assets/1.webp") },
{ url: require("./assets/2.webp") },
{ url: require("./assets/3.webp") },
{ url: require("./assets/4.webp") },
{ url: require("./assets/5.webp") },
{ url: require("./assets/6.webp") },
{ url: require("./assets/7.webp") },
{ url: require("./assets/8.webp") },
{ url: require("./assets/9.webp") },
{ url: require("./assets/10.webp") },
],
};
},
directives: {
async lazy(el, binding) {
// 默认图片
const def = await require('./assets/1.webp')
el.src = def
const observer = new IntersectionObserver((ob) => {
// 提供一个回调函数 // 如果 intersectionRatio 为 0,则目标在视野外,大于0 则在视野中
if(ob[0].intersectionRatio > 0) { // 处于可视区中
setTimeout(() => {
el.src = binding.value.url // 替换真实的地址
// 已经出现在可视区中则停止监听特定目标元素 避免再次加载
observer.unobserve(el)
}, 500)
}
})
// 监听的对象
observer.observe(el)
}
}
};
</script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.img {
width: 100%;
}
img {
width: 100%;
height: auto;
}
</style>
此时是默认图片,过了0.5s就会显示加载的图片,滚动到可视区域会替换默认图片