The effect
The overall analysis
A standalone global component that, if visible, tells the next page to load data, and if successfully loaded, is pushed to the bottom of the invisible until there is no more data to load
Code implementation
Component packaging
The structure and style of the component
<template>
<div class="infinite-loading" ref="container">
<! -- display while loading data -->
<div class="loading" v-if="isLoading">
<span class="img"></span>
<span class="text">Loading...</span>
</div>
<! -- Display data when all loaded -->
<div class="finished" v-if="isFinished">
<span class="text">Honey, there is no more</span>
</div>
</div>
</template>
<script>
export default {
name: 'InfiniteLoading'.props: {
// Whether it is loading
isLoading: {
type: Boolean.default: false
},
// All data is loaded
isFinished: {
type: Boolean.default: false}}}</script>
<style scoped lang='less'>
.infinite-loading {
.loading {
display: flex;
align-items: center;
justify-content: center;
height: 200px;
.img {
width: 50px;
height: 50px;
background: url('~@/assets/images/load.gif') no-repeat center / contain;
}
.text {
color: # 999;
font-size: 16px; }}.finished {
display: flex;
align-items: center;
justify-content: center;
height: 200px;
.text {
color: # 999;
font-size: 16px; }}}</style>
Copy the code
The component is registered globally after encapsulation and then tested on an empty page
/ / register.import InfiniteLoading from './infinite-loading'
export default {
install (app) {
...
app.component(InfiniteLoading.name, InfiniteLoading)
}
}
Copy the code
Renderings, pictures need to be changed
Function implementation
<script>
import { ref } from 'vue'
import { useIntersectionObserver } from '@vueuse/core'
export default {
name: 'InfiniteLoading'.emits: ['load'].props: {
isLoading: {
type: Boolean.default: false
},
isFinished: {
type: Boolean.default: false}},// Data lazy loading. If the component enters the viewable area, the parent component is told to load new data
+ setup (props, { emit }) {
+ const target = ref(null)
+ useIntersectionObserver(
+ target,
+ ([{ isIntersecting }], dom) = >{+if (isIntersecting) {
+ if (props.isLoading === false && props.isFinished === false) {+// The load event is triggered only when the data is not being loaded and not completely finished
+ emit('load')
+ }
+ }
+ }, {
+ threshold: 0+} +) +return { target }
+ }
}
</script>
Copy the code
Component Usage (Example)
rendering
implementation
setup(){...const isFinished = ref(false) // Check whether the load is complete
const isLoading = ref(false)
const loadData = () = > {
isLoading.value = true
findSubCategoryGoods(reqParams).then(res= > {
// reqParams is the request parameter
isLoading.value = false
if (res.result.items.length) {
isFinished.value = false
reqParams.page++
} else {
isFinished.value = true} goodList.value.push(... res.result.items) }) }return {isFinished,isLoading,loadData}
}
Copy the code