封装一个滚动时图片懒加载(v-lazy)指定

实现全局事件总线
  • 创建一个eventBus.js文件,代码如下
import Vue from "vue";

const listencers = {};

Vue.prototype.$bus = {
  //监听事件
  $on(eventName, handle) {
    //监听对象里面没有事件,加到对象里面
    if (!listencers[eventName]) {
      listencers[eventName] = new Set();
    }
    listencers[eventName].add(handle);
  },
  //取消监听
  $off(eventName, handle) {
    if (!listencers[eventName]) {
      return;
    }
    listencers[eventName].delete(handle);
  },
  //触发事件
  $emit(eventName, ...args) {
    if (!listencers[eventName]) {
      return;
    }
    for (const handle of listencers[eventName]) {
      //调用注册的方法
      handle(...args);
    }
  },
};
// const app = new Vue({});
// Vue.prototype.$bus = app;
export default Vue.prototype.$bus;
/**
 * 事件名:mainScroll
 * 含义:主区域滚动条变化后触发
 * 参数:
 * -滚动的dom元素,如果时undefined,则dom元素已经不存在
 *
 * 事件名:setMainScroll
 * 含义:当需要设置主区域滚条位置时触发
 *
 */
  • 在main.js中配置事件总线
import "./eventBus";
使用mixins的方式方便多个页面监听滚动事件,处理后续操作。
  • 创建一个mixins文件夹,文件夹下面mainScroll.js
export default function (refValue) {
  return {
    mounted() {
      //监听setMainScroll
      this.$bus.$on("setMainScroll", this.handleSetMainScroll);
      //监听滚动事件,滚动了就触发事件总线中的mainScroll事件
      this.$refs[refValue].addEventListener("scroll", this.handleMainScroll);
    },
    beforeDestroy() {
      this.$bus.$off("mainScroll", this.handleMainScroll);
      this.$bus.$off("setMainScroll", this.handleSetMainScroll);
      this.$refs[refValue].removeEventListener("scroll", this.handleMainScroll);
    },
    methods: {
      handleSetMainScroll(scrollTop) {
        this.$refs[refValue].scrollTop = scrollTop;
      },
      handleMainScroll() {
        //事件总线中触发mainScroll事件
        this.$bus.$emit("mainScroll", this.$refs[refValue]);
      },
    },
  };
}
封装v-lazy指令
  • 创建lazy.js文件
import eventBus from "../eventBus";
import { debounce } from "@/utils";
import defaultImg from "@/assets/loading.gif";
//调用该函数,就可以设置哪些合适的图片
let images = [];

/**
 * 处理单个图片
 * @param {} img
 */
function setImage(img) {
  //真实图片没加载之前的图片
  img.dom.src = defaultImg;
  //处理图片是否在视口内
  const rect = img.dom.getBoundingClientRect();
  const clientHeight = document.documentElement.clientHeight;
  const height = rect.height || 100;
  if (rect.top >= -height || rect.top <= clientHeight) {
    //在视口范围内
    const tempImg = new Image();
    tempImg.onload = function () {
      //当真实图片加载的时候,把真实的dom绑定服务器图片地址
      img.dom.src = img.src;
    };

    tempImg.src = img.src;
    //将加载好的图片移出数组
    images = images.filter((item) => item !== img);
  }
}

function setImages() {
  for (const image of images) {
    //处理图片
    setImage(image);
  }
}
function handleScroll() {
  setImages();
}

//监听事件总线名为mainScroll事件
eventBus.$on("mainScroll", debounce(handleScroll, 50));

export default {
  inserted(el, bindings) {
    images.push({
      dom: el,
      src: bindings.value,
    });
    setImages();
  },
  unbind(el) {
    images = images.filter((item) => item.dom !== el);
  },
};

其中debounce防抖函数如下:

export default function (fn, duration = 100) {
  let timeId = null;
  return (...args) => {
    clearTimeout(timeId);
    // 将该函数的this传递到fn
    timeId = setTimeout(() => {
      fn(...args);
    }, duration);
  };
}
  • 在main.js中注册自制指令
//入口文件
import "./mock";
import Vue from "vue";
import App from "./App.vue";
import "./style/global.less";
import "./eventBus";
import router from "./router";
import store from "./store";


//注册自制指令
import vLoading from "@/directive/loading";
import vLazy from "@/directive/lazy";
Vue.directive("loading", vLoading);
Vue.directive("lazy", vLazy);

new Vue({
  router,
  store,
  render: (h) => h(App),
}).$mount("#app");
使用mixins和v-lazy实现滚动时图片懒加载

  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值