自定义指令结合IntersetionObserver API实现上拉加载

        在使用vant组件库写移动端网页时,vant组件库并没有提供相关上拉加载的组件,因此只能自己手写一个,在了解了两种方案

(1)计算滚动条滚动的距离

(2)使用IntersetionObserver API

的简易程度后,决定使用IntersetionObserver API来实现上拉加载,这个方案比第一种简单太多了。

        要完成上拉加载,我们首先需要对页面的布局做相应的处理,具体布局如下:

<div class="team-container">
    <van-search
      v-model="searchValue.searchText"
      show-action
      placeholder="搜索队伍"
      shape="round"
      @search="handleSearchTeam"
    >
      <template #action>
        <div @click="addTeam">新增</div>
      </template>
    </van-search>
    <div class="team-list">
      <team-card-list
        ref="cardListRef"
        :team-list="teamList"
        :fetch-data="fetchData"
        @join-team="doJoinTeam"
        @update-team="doUpdateTeam"
      />
    </div>
  </div>

        页面tabbar部分为固定定位,脱离了文档流,搜索框为粘性定位,不会因为页面的滚动而滚动,因此只需要计算出剩下内容的高度,并设置overflow:scroll,并将父容器设置为overflow:hidden,这样就初步具备了上拉加载的可能。

.team-container {
	overflow: hidden;
	height: 100%;

	.team-list {
		overflow-y: scroll;
		height: 100%;
	}
}

        做好上面的步骤以后,我们还需要一个媒介,当这个媒介显示时,我们才开始触发上拉加载功能,这样就用到了IntersetionObserver API,当这个媒介在浏览器中显示时,这个API会监听到他的出现。这里,我选择了vant组件库提供的loading组件,需要注意的是,这个loading组件我们需要将它放在我们展示的所有内容的最后,不然IntersetionObserver API可能监听不到它的出现,类似下面:

<template v-for="user in userList" :key="user.id">
    <van-card
          :desc="user.profile"
          :title="`${user.username} (${user.planetCode})`"
        >
          <template #thumb>
            <van-image :src="user.avatarUrl" round width="80" height="80" />
          </template>

          <template #tags>
            <template v-for="(tag, index) in user.tags" :key="index">
              <van-tag type="primary">{{ tag }}</van-tag>
            </template>
          </template>
      </van-card>
</template>
<div class="loading">
    <van-loading
		type="spinner"
	    size="24px"
		v-loading="fetchData"
	    v-if="isShow"
	/>	
</div>

        做好以上布局之后,开始使用自定义指定来监听loading组件的出现,之所以使用自定义指令,是因为编写自定义指令在全局注册之后无论哪个页面都能使用。

        使用mounted这个钩子函数使得使用自定义指令的元素在挂载完成后调用,我们在使用自定义指令时可以传递一个可执行函数,我们在mounted这个钩子函数中开启监听loading组件的显示与隐藏,当显示时执行我们传递的可执行函数来加载新的数据,这样子就完成上拉加载了。

import type { Directive } from "vue";
import { useSettingStore } from "@/store/modules/setting";
type IPageInfo = {
  pageNumber: number;
  pageSize: number;
};
const settingStore = useSettingStore();
const vUpLoading: Directive<HTMLElement, (pageInfo?: IPageInfo) => void> = {
  mounted(el, binding) {
    let pageNumber = 1;
    const pageSize = 10;
    const observer = new IntersectionObserver((entries) => {
      const entry = entries[0];
      if (entry.intersectionRatio > 0) {
        settingStore.setLoading(true);
        binding.value({
          pageNumber: ++pageNumber,
          pageSize,
        });
      }
    });
    observer.observe(el);
  },
};

编写好这个指令之后,在主运行文件注册一下。

import vUpLoading from "./directives/up-loading";
const app = createApp(App);
app.directive("loading", vUpLoading);

注册完成之后,直接在页面元素使用就行了。

<van-loading
    type="spinner"
	size="24px"
	v-loading="fetchData"
	v-if="isShow"
/>

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

aklry

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

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

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

打赏作者

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

抵扣说明:

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

余额充值