vue3-vueuse-组件数据懒加载useIntersectionObserver

564 阅读1分钟

作用:实现当组件(DOM元素)进入可视区在加载数据

创建

src/hooks/index.js

// 提供复用逻辑的函数(钩子)
import { useIntersectionObserver } from '@vueuse/core'
import { ref } from 'vue'
// target 监听的目标 dom对象
/**
 * 数据懒加载函数
 * @param {Element} target DOM对象
 * @param {Function} apiFn api函数
 */
// 传入api
export const useLazyData = apiFn => {
  const result = ref([])
  const target = ref(null)
  // stop 停止观察
  const { stop } = useIntersectionObserver(
    // 监听的目标
    target,
    // isIntersecting 用来判断是否进入可视区
    // observerElement 被监听的DOM
    ([{ isIntersecting }], observerElement) => {
      // isIntersecting 是否进入可视区
      if (isIntersecting) {
        stop()
        // 调用api函数获取数据
        apiFn().then(data => {
          result.value = data.result
        })
      }
    },
    // 配置选项 相交比例
    {
      threshold: 0
    }
  )
  return { result, target }
}
组件中使用
<template>
<!-- 选择一个DOM节点,设置ref=‘target’ -->
<div ref="target" class="home-new">
  <home-panel title="新鲜好物" sub-title="新鲜出炉 品质靠谱">
    <template #right><xtx-more path="/" /></template>
    <Transition name="fade">
      <ul v-if="goods.length" class="goods-list">
        <li v-for="item in goods" :key="item.id">
          <RouterLink :to="`/product/${item.id}`">
            <img :src="item.picture" alt="">
            <p class="name ellipsis">{{item.name}}</p>
            <p class="price">&yen;{{item.price}}</p>
          </RouterLink>
        </li>
      </ul>
      <HomeSkeleton bg="#f0f9f4" v-else />
    </Transition>
  </home-panel>
</div>
</template>
<script>
// 引入钩子
import { useLazyData } from '@/hooks'
// 引入api
import { findNew } from '@/api/home'
import HomePanel from './home-panel'
import HomeSkeleton from './home-skeleton'
export default {
  name: 'home-new',
  setup () {
     // 使用钩子,有两个参数返回,result是api返回的数据,target是监听的DOM
    const { result, target } = useLazyData(findNew)
    return {
      goods: result,
      target
    }
  },
  components: {
    HomePanel, HomeSkeleton
  }
}
</script>