前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >AI简历开发-自定义指令实现图片懒加载

AI简历开发-自定义指令实现图片懒加载

作者头像
吃猫的鱼Code
发布2025-03-06 09:17:52
发布2025-03-06 09:17:52
3200
代码可运行
举报
运行总次数:0
代码可运行

前言

今天,为我的AI简历项目(https://github.com/weidong-repo/AIResume)的图片加载做一个小的优化。

当图片进入用户视图的时候再进行加载,减少用户访问的时候发送请求数量,优化访问体验。

下面开始记录一下整个流程

IntersectionObserver监听元素视图

IntersectionObserver 是一个浏览器 API,主要用于 监听 DOM 元素是否进入视口(或某个容器),适用于 懒加载、无限滚动、曝光统计 等场景。

代码语言:javascript
代码运行次数:0
复制
const observer = new IntersectionObserver(callback, options);
observer.observe(element);  // 观察某个元素
observer.unobserve(element); // 停止观察某个元素
observer.disconnect();  // 断开观察器,释放资源

其中:

options参数

options:配置观察器的参数,例如 触发条件观察区域

代码语言:javascript
代码运行次数:0
复制
const options = {
  root: document.querySelector('.container'),  // 观察区域 (默认是视口)
  rootMargin: '0px 0px -50px 0px', // 观察区域的外边距(类似 CSS margin)
  threshold: [0, 0.5, 1] // 触发回调的可见比例(0=完全不可见,1=完全可见)
};

callback回调函数

callback(entries, observer):当被观察的元素状态发生变化时,会触发 callback 回调函数。

回调函数callback(entries, observer)接收两个参数:

entries:表示当前所有被观察到的元素的信息(比如,在一次滑动页面的时候,有多个图片同时进入视口,这个时候,entries中就包含这些触发的元素)。entries是一个数组,数组中每个entry的一些关键属性:

代码语言:javascript
代码运行次数:0
复制
{
  time: 12345678,          // 触发回调的时间戳
  target: element,         // 被观察的 DOM 元素
  intersectionRatio: 0.5,  // 目标元素的可见比例 (0 ~ 1)
  isIntersecting: true,    // 是否进入观察区域 (true=进入, false=离开)
  boundingClientRect: {},  // 目标元素的尺寸 & 位置
  intersectionRect: {},    // 目标元素的可见部分信息
  rootBounds: {},          // 根容器的尺寸 & 位置
}

observer:当前 IntersectionObserver 实例。

vue3中directive自定义指令

是什么?

在 Vue 3 中,自定义指令允许你直接操作 DOM 元素,类似于原生的 v-ifv-for,但你可以为它们创建自定义行为。Vue 3 中的指令系统进行了优化,支持全局和局部注册,可以与 TypeScript 很好地配合使用。

基本使用(快速开始)

在main.ts中全局注册自定义指令

代码语言:javascript
代码运行次数:0
复制
import { createApp } from 'vue';
import App from './App.vue';

const app = createApp(App);

app.directive('focus', {
  mounted(el) {
    el.focus(); // 在元素挂载到 DOM 后自动获取焦点
  }
});

app.mount('#app');
代码语言:javascript
代码运行次数:0
复制

生命周期函数钩子

自定义指令的生命周期函数钩子:

beforeMount:指令在绑定元素的父组件挂载之前调用。

mounted:指令在元素被挂载到 DOM 后调用。

beforeUpdate:指令在所在组件的 VNode 更新之前调用。

updated:指令在所在组件的 VNode 更新之后调用。

beforeUnmount:指令在元素从 DOM 中移除之前调用。

unmounted:指令在元素从 DOM 中移除后调用。

传参:

每个钩子函数都会传入不同的参数:

  • el:指令所绑定的元素,通常是一个 DOM 元素。
  • binding:一个对象,包含指令的信息,如参数、值等。
  • vnode:虚拟节点,包含了 Vue 内部的 VNode 数据。
  • prevVnode:前一个虚拟节点,只有在更新过程中才可用。

一个示例:

代码语言:javascript
代码运行次数:0
复制
app.directive('tooltip', {
  mounted(el, binding) {
    const tooltipText = binding.value || '默认提示';  // 使用传入的值
    const tooltipPosition = binding.arg || 'top';  // 使用动态参数,默认值为 'top'
    // 创建 tooltip 元素
    const tooltip = document.createElement('span');
    tooltip.innerText = tooltipText;
    tooltip.style.position = 'absolute';
    tooltip.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
    tooltip.style.color = 'white';
    tooltip.style.padding = '5px';
    tooltip.style.borderRadius = '4px';
    tooltip.style.visibility = 'hidden';
    // 根据修饰符调整显示位置
    if (binding.modifiers.bottom) {
      tooltip.style.top = '100%';
    } else {
      tooltip.style.bottom = '100%';
    }
    // 将 tooltip 插入到目标元素
    el.style.position = 'relative';
    el.appendChild(tooltip);
    // 显示 tooltip
    el.addEventListener('mouseenter', () => {
      tooltip.style.visibility = 'visible';
    });
    // 隐藏 tooltip
    el.addEventListener('mouseleave', () => {
      tooltip.style.visibility = 'hidden';
    });
  },
});

Vue3中实现图片懒加载的自定义指令

首先是lazyLoad.ts,在这里定义了mounted生命周期,对元素指令绑定的元素进行钩子监听。

并且定义了一个回调函数loadImage,并且在IntersectionObserver进行监控触发回调,当图片即将进入视口的时候,触发回调,把图片url替换回图片原本的地址(一开始默认是loading图)

代码语言:javascript
代码运行次数:0
复制
import myImage from '@/assets/imgs/loading.gif';
export default {
  mounted(el: HTMLImageElement, binding: any) {
    el.src = myImage
    const loadImage = (entries: IntersectionObserverEntry[], observer: IntersectionObserver) => {
      const entry = entries[0];
      if (entry.isIntersecting) {
        el.src = binding.value;
        observer.unobserve(el);
      }
    };
    const observer = new IntersectionObserver(loadImage, { root: null, threshold: 0.1 });
    observer.observe(el);
    (el as any).__lazyObserver__ = observer; // 绑定 observer 到元素
  },
  unmounted(el: HTMLImageElement) {
    if ((el as any).__lazyObserver__) {
      (el as any).__lazyObserver__.disconnect();
    }
  }
};

main.ts中使用,加入下面两行

代码语言:javascript
代码运行次数:0
复制
import lazyLoad from './directives/lazyLoad';

app.directive('lazy', lazyLoad);

组件中直接使用:

代码语言:javascript
代码运行次数:0
复制
<img v-lazy="getTemplateImage(template)" :alt="template.name" class="template-image" />
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025年03月05日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • IntersectionObserver监听元素视图
    • options参数
    • callback回调函数
  • vue3中directive自定义指令
    • 是什么?
    • 基本使用(快速开始)
    • 生命周期函数钩子
  • Vue3中实现图片懒加载的自定义指令
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档