8000 Intersection Observer + Vue指令 优雅实现图片懒加载 · Issue #73 · amandakelake/blog · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
Intersection Observer + Vue指令 优雅实现图片懒加载 #73
@amandakelake

Description

@amandakelake

基础(必会)

参考链接:Intersection Observer API - Web API | MDN

思路

  • 创建LazyLoadImage类,全局只实例化一次,执行init方法
  • 每个img标签被创建时,自动将添加到观察者队列
    • 没进入视窗时,src被赋予了loading图片地址,真实的地址被保存在data-src属性中
    • 进入视窗后,从data-src属性中取出真正的地址,赋予给src属性,完成加载
  • 加载完图片后,把该img标签从观察者队列中删除,不再被观察

创建一个全局的LazyLoadImage

// 引入polyfill,解决兼容性问题
import 'intersection-observer'; 
IntersectionObserver.prototype['THROTTLE_TIMEOUT'] = 300;
const DefaultLoadingImage = '默认loading图片'

export default class LazyLoadImage {
  _observer: IntersectionObserver | null;
  _loadingImage: string;

  constructor(option: object = {}) {
    this._observer = null;
    // @ts-ignore
    this._loadingImage = option.loading || DefaultLoadingImage;
    this.init();
  }

  init() {
    this._observer = new IntersectionObserver(entries => {
      entries.forEach(entry => {
        // 触发进入视窗条件,替换真正的图片链接到src属性上
        if (entry.isIntersecting) {
          // @ts-ignore
          const url = entry.target.getAttribute('data-src');
          // @ts-ignore
          entry.target.setAttribute('src', url);
          entry.target.setAttribute('data-src', '');
	  // 替换真正的线上地址后,取消对该元素的观察
          this._observer && this._observer.unobserve(entry.target);
        }
      })
    }, {
      root: null,
      rootMargin: "500px 200px 1000px 200px", // 扩大视窗范围,提前加载
      threshold: 0.1
    })
  }	

// 让每个img标签自行调用add方法,把自己添加到观察者队列中
  add(entry: any) {
    this._observer && this._observer.observe(entry.el);
  }
}

封装vue指令

// 全局只实例化一个类,实例执行init方法自己创建观察者队列
const lazyload = new LazyLoadImage();
// 让每个img标签自行调用add方法,把自己添加到观察者队列中
// 用法: <img v-lazy="图片地址" />
Vue.directive('lazy', {
    bind(el, binding) {
        el.setAttribute('data-src', binding.value);
        el.setAttribute('src', lazyload._loadingImage);
        lazyload.add({el: el, val: binding.value});
    }
})

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0