性能优化之自定义指令实现图片懒加载

1)图片懒加载

是常见的用于在页面滚动时动态加载图片,而不是在页面加载时一次性加载所有图片。性能优化必备提高页面加载速度的手段,特别是在包含大量图片的网站上。

图片懒加载的原理,其实就是,当图片出现在视口内时,进行图片的加载。

市场上也有成熟的第三方库可以帮助我们实现图片懒加载,如 Vue Lazyloadvue3-lazy

不过在这里,我通过自己的理解,使用浏览器 API------Intersection Observer 实现图片懒加载自定义指令

2)看图说话
3)自定义指令(代码中有详解讲解IntersectionObserver用法)
复制代码
// src/directives/layload/index.js
// 图片加载中时占位
import loadingImg from '../../asset/layload/loadingImg.gif'
// 图片加载错误时占位
import errorImg from '../../asset/layload/errorImg.png'
export default {
  mounted(el, binding) {
    el.src = loadingImg
    // IntersectionObserver 接口提供了一种异步观察目标元素
    // 与其祖先元素或顶级文档视口(viewport)交叉状态的方法。
    el.Intersection = new IntersectionObserver((entries) => {
      // 如果交叉,则背景图片替换成绑定图片
      if (entries[0].isIntersecting) {
        el.src = binding.value.src
        // 加载成功
        el.onload = (res) => {
          console.log('加载成功', res)
        };
        // 加载失败了需要做一个错误图片的占位
        el.onerror = (err) => {
          console.log('加载失败', err);
          el.src = errorImg
        }
      }
    })
    el.Intersection.observe(el)
  },
  unmounted(el, binding) {
    el.Intersection.unobserve(el)
  }
}

// directives/index.js
import layload from "./layload"
// 自定义指令对象,用于遍历注册
const directives = {
  layload
}
// 批量注册指令并暴露到main.js中去便于注册
export default {
  install(app) {
    Object.keys(directives).forEach((key) => {
      app.directive(key, directives[key])
    })
  }
}

// main.js中引入以下代码
 
// 引入并使用自定义指令
import directive from './directives'
app.use(directive);

<!-- 自定义指令 -->
<template>
  <h4>图片懒加载自定义指令</h4>
  <div class="imgBox">
    <img class="image" v-layload="img" v-for="img in imgList" :key="img">
  </div>
</template>

<script setup>
import { ref } from 'vue'
const imgList = [
  {
    src: "http://ashuai.work:10000/imgSrc/html.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/css.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/js.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/nodejs.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/webpack.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/vue.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/react.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/angular.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/ie.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/chrome.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/firefox.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/safari.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/edge.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/http.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/uniapp.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/wx.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/leetcode.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/java.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/spring.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/mybatis.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/redis.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/mysql.png",
  },
  {
    src: "http://ashuai.work:10000/imgSrc/oracle.png",
  },
  {
    src: "占位",
  }
]

const handleSizeChange = (val) => {
  console.log(`${val} items per page`)
}
const handleCurrentChange = (val) => {
  console.log(`current page: ${val}`)
}
</script>
<style scoped>
.demo-pagination-block+.demo-pagination-block {
  margin-top: 10px;
}

.demo-pagination-block .demonstration {
  margin-bottom: 16px;
}

.imgBox {
  width: 100%;
  display: flex;
  justify-content: flex-start;
  flex-wrap: wrap;
}

.image {
  width: 200px;
  height: 200px;
}
</style>

很多问题有多种解决方案,深入探究,前进。

积跬步,至江河。加油ヾ(◍°∇°◍)ノ゙

相关推荐
颜酱29 分钟前
图结构完全解析:从基础概念到遍历实现
javascript·后端·算法
小迷糊的学习记录1 小时前
Vuex 与 pinia
前端·javascript·vue.js
发现一只大呆瓜1 小时前
前端性能优化:图片懒加载的三种手写方案
前端·javascript·面试
不爱吃糖的程序媛2 小时前
Flutter 与 OpenHarmony 通信:Flutter Channel 使用指南
前端·javascript·flutter
利刃大大2 小时前
【Vue】Element-Plus快速入门 && Form && Card && Table && Tree && Dialog && Menu
前端·javascript·vue.js·element-plus
NEXT062 小时前
AI 应用工程化实战:使用 LangChain.js 编排 DeepSeek 复杂工作流
前端·javascript·langchain
光影少年3 小时前
react的hooks防抖和节流是怎样做的
前端·javascript·react.js
小毛驴8503 小时前
Vue 路由示例
前端·javascript·vue.js
发现一只大呆瓜3 小时前
AI流式交互:SSE与WebSocket技术选型
前端·javascript·面试
wuhen_n4 小时前
JavaScript链表与双向链表实现:理解数组与链表的差异
前端·javascript