作用:实现当组件(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">¥{{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>