实现当组件进入可视区域在加载数据。
使用 @vueuse/core
中的 useIntersectionObserver
来实现监听进入可视区域行为.
vueuse它是为Vue 2和Vue 3服务的一套Vue Composition API的常用工具集,是目前世界上Star最高的同类型库之一。它的初衷就是将一切原本并不支持响应式的JS API变得支持响应式,省去程序员自己写相关代码。
具体实践如下
// 提供复用逻辑的函数(钩子) 数据懒加载
import { useIntersectionObserver } from '@vueuse/core'
import { ref } from 'vue'
/**
* 数据懒加载函数
* @param {object} target --DOM对象
* @param {function} apiFn ---API函数
*
*/
export const useLazyData = (apiFn) => {
const result = ref([])
const target = ref(null)
// stop停止观察
const { stop } = useIntersectionObserver(
// 监听目标元素
// target 是观察的目标dom容器,必须是dom容器,而且是vue3.0方式绑定的dom对象
target,
// isIntersecting 是否进入可视区域,true是进入 false是移出
// observerElement 被观察的dom
([{ isIntersecting }], observerElement) => {
// 在此处可根据isIntersecting来判断,然后做业务
if (isIntersecting) {
// console.log('进入可是去')
stop()
// 调用API 函数获取数据
apiFn().then(data => {
result.value = data.result
})
}
}
)
return { result, target }
}
二 :在组件中引入 看注释
<template>
<div class='home-new'>
<HomePanel title="新鲜好物" sub-title="新鲜出炉 品质靠谱 ">
<template #right>
<XtxMore path="/" />
</template>
<!-- 引入 target去绑定一个监听对象 最好是DOM -->
<div ref="target" style="position:relative;height:426px;">
<!-- 面板内容 -->
<!-- 动画效果 -->
<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>
</div>
</HomePanel>
</div>
</template>
<script>
import HomePanel from './home-panel.vue'
import HomeSkeleton from './home-skeleton.vue'
import { findNew } from '@/api/home'
import { useLazyData } from '@/hooks'
export default {
name: 'HomeNew',
components: {
HomePanel,
HomeSkeleton
},
setup () {
//普通加载
// const goods = ref([])
// findNew().then(data => {
// goods.value = data.result
// })
// 数据懒加载
// const target = ref(null)
// 1.target去绑定一个监听对象 最好是DOM
// 2.传入API函数 内部获取调用 返回的就是响应式数据
const { target, result } = useLazyData(findNew)
return { goods: result, target }
}
}
</script>
<style scoped lang='less'>
.goods-list {
display: flex;
justify-content: space-between;
height: 406px;
li {
width: 306px;
height: 406px;
background: #f0f9f4;
.hoverShadow();
img {
width: 306px;
height: 306px;
}
p {
font-size: 22px;
padding: 12px 30px 0 30px;
text-align: center;
}
.price {
color: @priceColor;
}
}
}
</style>