vue图片懒加载插件封装

300 阅读1分钟

未进入窗口的图片资源,展示骨架屏动画

#IntersectionObserver #骨架屏动画

实现

template 模板

<template>
  <!-- 懒加载 -->
  <div class="lazy-load" :class="{ loading: isLoad }" ref="lazyLoad">
    <img src="" alt="" srcset="" />
  </div>
</template>

js 部分

 这里主要使用IntersectionObserver api  传入一个callback 接收一个数组对象。
 当页面滚动时候,自动调用callback,我们可以判断对象的isIntersecting 属性。
 当为true时,src 地址赋值给图片,并在加载完成的时候是骨架屏动画消失。
export default {
  name: "lazyLoad",
  props: {
    src: {
      type: String,
      default: "",
    },
  },
  data() {
    return {
      isLoad: true,  // 图片状态
    };
  },
  mounted() {
    let node = this.$refs["lazyLoad"]; // 获取节点
    let observer = new IntersectionObserver((entries) => {
      //是否进入视野
      let flag = entries.some(entry =>entry.isIntersecting);
      if (flag) {
        // 图片加载
        let img = node.querySelector("img");
        img.src = this.src;
        img.onload = () => {
          this.isLoad = false; // 骨架屏动画消失
        };

        // 停止观察
        observer.disconnect();
      }
    });
    observer.observe(node);
  },
};

scss 部分

/* 骨架屏动画 */
@keyframes skeleton-ani {

  from {
    left: -100%;
  }

  to {
    left: 150%;
  }
}

.lazy-load {
  // width: 100%;
  min-height: 60px;
  display: block;
  img {
    // width: auto;
    flex: 1;
    width: 100%;
  }
  // 加载效果
  &.loading {
    pointer-events: none;
    position: relative;
    background-color: #ccc;
    overflow: hidden;
    &::after {
      position: absolute;
      top: 0;
      width: 30%;
      height: 100%;
      content: "";
      background: linear-gradient(
        to right,
        rgba(255, 255, 255, 0) 0,
        rgba(255, 255, 255, 0.3) 50%,
        rgba(255, 255, 255, 0.3) 70%,
        rgba(255, 255, 255, 0) 100%
      );
      transform: skewX(-45deg);
      z-index: 99;
      animation: skeleton-ani 1s ease infinite;
      display: block;
    }
  }
}

使用

<template>
  <div>
    <lazy-load src="http://192.168.100.101:5500/img?name=cat"></lazy-load>
  </div>
</template>
<script>
import lazyLoad from "./lazyLoad.vue";
export default {
  components: {
    lazyLoad,
  },
 }
</script>