目的:实现当组件/DOM元素进入浏览器可视区域再发送Ajax请求加载数据。
我们可以使用 @vueuse/core
中的 useIntersectionObserver
来实现监听进入可视区域行为,但是必须配合vue3.0的组合API的方式才能实现。
1.安装@vueuse/core
npm i @vueuse/core@5.3.0
// 安装依赖包的时候要注意版本,有时最新版本会与项目之间有冲突
2.理解 useIntersectionObserver 的使用,各个参数的含义
// const { stop } = useIntersectionObserver(target, fn, options)
// 1、参数一target表示被监听的DOM元素
// 2、参数二是回调函数,用于通知监听的动作(回调函数的第一个形参isIntersecting为true表示被监听的元素已经进入可视区域;为false时表示离开可视区域)
// 3、表示配置选项
// stop 是否停止观察进入或移出可视区域的行为,为stop()方法
const { stop } = useIntersectionObserver(
// target 是观察的目标dom容器,必须是dom容器,而且是vue3.0方式绑定的dom对象
target,
// isIntersecting 是否进入可视区域,true是进入 false是移出
// observerElement 被观察的dom
([{ isIntersecting }], observerElement) => {
// 在此处可根据isIntersecting来判断,然后做业务
}
)
3.使用
在一个测试组件内简单使用
<template>
<div>默认可视区域</div>
<p ref="target" style="background:cornflowerblue;height:50px;">
测试DOM元素
</p>
</template>
<script>
import { useIntersectionObserver } from '@vueuse/core'
import { ref } from 'vue'
export default {
name: 'Test',
setup () {
const target = ref(null) // 定义target
const { stop } = useIntersectionObserver(target, ([{ isIntersecting }]) => {
if (isIntersecting) {
stop() // 进入可视窗口后,停止对该元素的监听
// 可以在此处发送ajax请求操作
console.log('测试DOM元素进入可视区域') // 浏览器进入可视窗口时打印
}
})
return { target }
}
}
</script>
<style lang="less" scoped>
div{
height: 700px;
}
</style>
默认可视窗口
测试元素进入可视窗口
4.复用封装
// 封装一个通用的方法实现数据的懒加载
import { useIntersectionObserver } from '@vueuse/core'
import { ref } from 'vue'
export const useLazyData = (apiFn) => {
// apiFn为传入的ajax请求api
// target表示组件的最外层div元素
const target = ref(null)
// 懒加载接口返回的数据
const result = ref([])
// 监听组件是否进入可视区
const { stop } = useIntersectionObserver(target, ([{ isIntersecting }]) => {
// 如果target对应的DOM进入可视区,那么该回调函数就触发
if (isIntersecting) {
// 被监听的DOM进入了可视区:此时调用接口获取数据;停止继续监听
stop()
apiFn().then(res => {
result.value = res.xxx
})
}
})
// result表示接口懒加载获取的业务数据
// target表示被监听的DOM元素,需要在模板中被ref属性绑定
return { result, target }
}
<template>
<!-- 监听内部封装组件 -->
<my-component ref="target"/>
</template>
<script>
// 组件内使用
import { useLazyData } from '@/xxx/index.js'
import { 真实的api接口方法 } from '@/xxxx/index.js'
setup () {
// 不需要参数
const { result, target } = useLazyData(真实的api接口方法)
// 如果api接口需要传入参数
const { result, target } = useLazyData(() => 真实的api接口方法(参数))
return { result, target }
}
</script>