vue-lazyload图片懒加载实现

vue-lazyload自实现

vue学习 vue-lazyload组件的实现



前言

提示:这里可以添加本文要记录的大概内容:

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、vue-lazyload是什么?

实现图片懒加载

二、使用步骤

1.引入库

代码如下(示例):

import Vue from "vue";
import App from "./App.vue";
import MyLazLoad from "@/my-lazload";

Vue.config.productionTip = false;
Vue.use(MyLazLoad, {
  loading:
    "",
  preload: 1,
});
new Vue({
  render: (h) => h(App),
}).$mount("#app");

## 2.具体实现js代码部分

代码如下(示例):

```c
/*
懒加载效果,实际图片出现前加载默认图片
默认加载可视区域的图片 不显示部分的不加载
滚动图片 添加滚动监听
对外抛出不是一个类,外部没有实例化
preload预加载方式,相对可视区域高度的倍数 
*/
function getScrollParent(el) {
  //获取子元素绑定overf:scroll auto属性的父元素
  let parent = el.parentNode;
  while (parent) {
    if (/(scroll)|(auto)/.test(getComputedStyle(parent)["overflow"])) {
      return parent;
    }
    parent = parent.parentNode;
  }
  return null;
}
//同步加载图片
function asyncImgLoad(src, resove, reject) {
  let img = new Image();
  img.src = src;
  img.onload = resove;
  img.error = reject;
}
//对逻辑功能进行拆分
const MyLaz = (Vue) => {
  //为了实现元素和对象的关联,创建一个绑定对象
  class ReactiveListene {
    constructor({ el, src, renderEl, preload }) {
      this.el = el;
      this.src = src;
      this.renderEl = renderEl;
      this.preload = preload;
      this.state = { loading: false }; //还没有加载
    }
    //检测是不是在可视区域的范围内
    checkInViem() {
      let { top } = this.el.getBoundingClientRect();
      return top < window.innerHeight * this.preload;
    }
    //加载图片的方法
    load() {
      //优先加载loading
      this.renderEl(this, "loading");
      //加载实际图片
      asyncImgLoad(
        this.src,
        () => {
          //图片加载成功后,渲染成功图片
          //   setTimeout(() => {
          //延时器效果更加明显 方便观察
          //     this.state.loading = true;
          //     this.renderEl(this, "success");
          //   }, 1000);
          this.state.loading = true;
          this.renderEl(this, "success");
        },
        () => {
          //图片加载失败后,渲染失败图片
          this.renderEl(this, "error");
        }
      );
    }
  }
  return class LazClass {
    constructor(options) {
      const { preload, loading } = options;
      this.preload = preload || 1;
      this.loading = loading;
      //   绑定滚动事件初始
      this.bindScrollEvent = false;
      //保存所有元素
      this.listenerArr = [];
    }
    handleScroll() {
      // 滚动的监听事件
      this.listenerArr.map((listener) => {
        //验证是否加载
        if (!listener.state.loading) {
          let isInView = listener.checkInViem();
          isInView && listener.load();
        }
        return listener;
      });
    }
    add(el, bindings) {
      //添加滚动监听
      //将图片对应的listener对象存起来
      Vue.nextTick(() => {
        const scrollBox = getScrollParent(el);
        if (scrollBox && !this.bindScrollEvent) {
          this.bindScrollEvent = true;
          scrollBox.addEventListener("scroll", this.handleScroll.bind(this));
        }
        //在绑定元素的时候添加检测对象
        const listener = new ReactiveListene({
          el,
          src: bindings.value,
          renderEl: this.renderEl.bind(this),
          preload: this.preload,
        });
        this.listenerArr.push(listener);
        //初始化触发
        this.handleScroll();
      });
    }
    // 渲染方法
    renderEl(listener, state) {
      let el = listener.el;
      let src = "";
      switch (state) {
        case "loading":
          src = this.loading;
          break;
        case "error":
          src = "";
          break;
        default:
          src = listener.src;
          break;
      }
      el.setAttribute("src", src);
    }
  };
};
//注册自定义指令
const MyLazLoad = {
  install(Vue, options) {
    //创建自定义指令
    const LazClass = MyLaz(Vue);
    const laz = new LazClass(options);
    Vue.directive("zby", {
      //钩子函数bind:只调用一次,指令第一次绑定元素时调用,这儿可以进行一次初始化设置
      bind: laz.add.bind(laz), //目的是调用add方法时候,this能够指向的是实例
    });
  },
};
export default MyLazLoad;



#APP.vue 部分
<template>
  <div id="app">
    <div class="box">
      <ul>
        <li v-for="(item, index) in list" :key="index">
          <img v-zby="item.imgurl" alt="" />
        </li>
      </ul>
    </div>
  </div>
</template>
<script>
import axios from "axios";
export default {
  name: "App",
  data() {
    return {
      list: [],
    };
  },
  async mounted() {
    const res = await axios.get("/fcj/music/getRecommendList");
    this.list = res.data.data.list;
    console.log(this.list);
  },
};
</script>
<style lang="less">
.box {
  width: 200px;
  height: 400px;
  border: 1px solid pink;
  overflow: scroll;
  li {
    list-style: none;
    width: 120px;
    height: 120px;
    img {
      width: 100%;
      height: 100%;
    }
  }
}
</style>


总结

仅供参考 谢谢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值