前端页面性能优化:实现页面组件的懒加载

目录

实现原理

特点

效果图

组件代码 

调用方式

注意点


实现原理

懒加载组件LazyContainer的实现原理是通过IntersectionObserver实例来监听页面元素是否进入可视化窗口,只有当元素可见时,才初始化组件,避免了不必要的资源浪费。

IntersectionObserver是一个由浏览器提供的JavaScript接口,它能够追踪元素与视窗的交互情况。此API能够告知开发者,某个元素是否正处于视窗内或正离开视窗,同时还能提供关于两者相交部分的详细信息,包括大小和具体位置。

特点

  • 非阻塞性质:该 API 以异步方式运行,利用浏览器的高效内部处理机制,不会影响到主线程的运行,有效避免了性能瓶颈。
  • 资源高效:与传统的滚动事件监听或定时器相比,IntersectionObserver 能够精确监测元素与视窗的相交情况,减少了不必要的计算和回调函数的触发,从而降低了资源消耗。
  • 多元素监控:IntersectionObserver 允许同时对多个元素进行监控,通过回调函数逐一通知开发者在视窗中的相交状态,便于实现批量处理。
  • 阈值自定义:开发者可以设置一个或多个阈值,以定义元素与视窗相交的程度。一旦相交比例达到或低于这些阈值,便会激活相应的回调函数。

利用 IntersectionObserver,开发者能够轻松实现诸如图片懒加载、滚动加载更多内容、广告可见性控制等功能,这些都能够显著提高网页的性能和用户的互动体验。

官方api:交叉观察器 API - Web API 接口参考 | MDN

效果图

例如下方图中转圈的卡片是页面滚动条往下拉后刚出现在页面中的,表示正在调用接口和初始化操作,上面没有转圈的表示已经渲染完毕的卡片。

懒加载页面示例

组件代码 

懒加载组件LazyContainer的代码如下:

<template>
  <div ref="container">
    <slot v-if="isInit"></slot>
    <!--组件初始化之前显示加载态loading-->
    <div key="skeleton" v-else style="height: 100%; width: 100%">
      <!-- 如果提供了骨架屏插槽,则显示它 -->
      <slot name="skeleton" v-if="$slots.skeleton"></slot>
      <!-- 否则显示默认的加载态 -->
      <div v-else class="skeleton-item"></div>
    </div>
  </div>
</template>
<script setup defer>
  import { onMounted, onUnmounted, ref } from 'vue';

  const container = ref(null);
  const isInit = ref(false);
  const timer = ref();
  onMounted(() => {
    // 创建一个Intersection Observer对象来观察元素是否进入视口
    const observer = new IntersectionObserver((entries) => {
      // 如果元素进入视口,设置定时器,800毫秒后设置isInit为true
      if (entries[0].isIntersecting) {
        timer.value = setTimeout(() => {
          isInit.value = true;
          // 在组件卸载时取消观察
          observer.unobserve(container.value);
        }, 800);
      }
    });
    // 开始观察container元素
    observer.observe(container.value);
  });
  onUnmounted(() => {
    clearTimeout(timer.value);
  });
</script>
<style scoped>
  /*样式二*/
  .skeleton-item {
    width: 100%;
    height: 100%;
    background-color: #f3f3f3;
    border-radius: 10px;
    overflow: hidden;
  }

  .skeleton-item:empty {
    background-color: #f2f2f2;
  }

  .skeleton-item:empty::before {
    /* 内容区域空状态时追加骨架屏样式 */
    content: '';
    display: block;
    width: 100%;
    height: 100%;
    transform: translateX(-100%);
    background: linear-gradient(90deg, transparent, rgba(225, 225, 225, 0.753), transparent);
    animation: loading 1s infinite;
  }

  @keyframes loading {
    100% {
      transform: translateX(100%);
    }
  }
</style>

调用方式

test_div是需要被懒加载的组件或元素

<template>
    <div class="lazyCard">
      <div v-for="(item, index) in 50" :key="index" style="height: 500px">
        <lazy-container style="height: 200px;width: 200px">
          <div class="test_div"></div>
        </lazy-container>
      </div>
    </div>
</template>
<script lang="ts" setup>
  import LazyContainer from '@/components/LazyComponents/LazyContainer.vue';
</script>
<style scoped lang="less">
  .lazyCard {
    height: 800px;
    width: 800px;
    padding: 10px;
    margin: 0;
    display: grid;
    border-radius: 5px;
    box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.12);
    grid-template-columns: repeat(3, 1fr);
    overflow: auto;
  }
  .test_div {
    height: 200px;
    border: 1px solid #e0e3ea;
    background-color: #7b7d80;
    border-radius: 10px;
  }
</style>

当页面存在多个test组件时,不使用懒加载,将会同时渲染,同时调用接口,会造成页面的卡顿,非常影响体验。而使用了懒加载后,只有当进入页面可视区域的test组件才会初始化渲染,提高页面加载速度。

注意点

LazyLoader组件中的setTimeout设置了一个延迟时间,确保在组件初始化之前显示一个加载状态框,避免了显示空白区域的突兀感。同时,懒加载组件的宽度和高度需要与监听的组件高度宽度一致,这样加载时loading态的骨架屏才会和需要懒加载的组件大小一致。

  • 16
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

马可家的菠萝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值