IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> [javascript]手写一个懒加载组件 -> 正文阅读

[JavaScript知识库][javascript]手写一个懒加载组件

参考一下vantui里的List组件,实现一个印象中的懒加载功能(之所以说是印象中呢主要是vant打不开鸭,全凭记忆中的功能来摸索了);

不是我想重复造轮子,是我想自定义一些些功能。。。

逻辑 主要是监听滚动条 计算设置好的滚动条到底部的高度来异步加载数据,期间异步加载尚未结束时不会重复执行加载操作,所以应该是用了节流。

废话不多说,开始coding

先声明一个组件 就叫他LazyLoad吧

  <div class="lazy-load-ctx" ref="scrollRef">
    <div class="scroll-ctx" ref="scrollCtxRef">
      <slot name="child"></slot>
      <div v-show="props.finish" class="not-data">没有更多数据了~</div>
    </div>
  </div>

ts 这里用了vue3的setup语法糖 定义了传过来的参数以及一个onLoad异步加载数据的方法

const props = defineProps({
  finish: {// 数据完全加载完成
    type: Boolean,
    default: false,
  },
  loading: {// 正在加载中
    type: Boolean,
    default: false,
  },
  offset: {// 距离底部的高度
    type: Number,
    default: 300,
  },
  height: {// 整个滚动容器的高度
    type: String,
    default: "100%",
  },
});
const emit = defineEmits(["onLoad"]);

const scrollRef = ref(null);
const scrollCtxRef = ref(null);

css

.lazy-load-ctx {
  height: v-bind("props.height");
  overflow-y: auto !important;
  .scroll-ctx {
    height: auto;
  }
  .not-data {
    text-align: center;
  }
}

声明一个节流函数

function throttle<T>(cb: (e: T) => void) {
  let state = false;
  return (e: T) => {
    if (state) return;
    cb(e);
    state = true;

    setTimeout(() => {
      state = false;
    }, 100);
  };
}

页面挂载的时候给容器添加滚动监听事件 首次进来的时候触发onload加载数据的方法;我这里还监听了鼠标滚轮事件,防止数据量小的时候没有撑开容器高度导致无滚动条接连无法触发滚动监听(好像有点多余,Orz)

onMounted(() => {
  emit("onLoad");
  const dom = scrollRef.value as HTMLDivElement;
  dom.addEventListener("scroll", throttle<Event>(onScroll));
  dom.addEventListener("wheel", throttle<WheelEvent>(addEventWheel));
});

onScroll函数
获取滚动条到底部的高度

function onScroll(e: Event) {
  // 正在加载或者加载完所有数据了停止执行
  if (props.finish || props.loading) return;
  if (e.target instanceof HTMLDivElement) {
    const { scrollHeight, scrollTop, offsetHeight } = e.target;
    const scrollBottom = scrollHeight - scrollTop - offsetHeight;
    if (scrollBottom < props.offset) {
      // 超过了300开始加载数据喔
      emit("onLoad");
    }
  }
}

hasScroll函数
判断页面有无滚动条

function hasScroll() {
  return document.body.offsetHeight < (scrollCtxRef.value as HTMLDivElement).offsetHeight;
}

addEventWheel函数
监听鼠标滚轮事件

function addEventWheel(e: WheelEvent) {
  const state = hasScroll();
  // 当前有尚未加载完的数据并且无滚动条且是向下滚动且非加载状态
  if (!props.finish && !state && e.deltaY > 0 && !props.loading) {
    emit("onLoad");
  } else return;
}

最后页面卸载的时候记得去清除监听事件
我这里用了节流函数去监听事件,由于用了闭包,每次节流函数都返回了随机的字符,而移除监听事件必须得和添加监听事件的名称一致 导致了现在正常是无法去移除监听事件的,需要对节流函数做一下修改 这里有改造节流函数

onUnmounted(() => {
  const dom = scrollRef.value as HTMLDivElement;
  // dom.removeEventListener("scroll", throttle<Event>(onScroll));
});

大致功能就是这样 vue/react拿来改改就能用了

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-26 11:33:45  更:2022-04-26 11:37:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:03:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码