Scroll to load more components on mobile

preface

There was a feature point on the mobile side that was about scrolling to the bottom, and then automatically executing the next request. Originally thought to use the company’s internal basic components, but found that the basic components are not available (internal generally prohibited to introduce some large company components, risk problems).

I have seen other open source single components, all of which are quite good, but the overall amount of code is quite large, and there is a psychological rejection in my heart, so…

I had no choice but to masturbate

implementation

configuration
configuration The default value note
pageIndex 1 Paging request index
pageSize 10 Paging request size
totalCount 0 Paging request count
delay 500(ms) Delay request
bottom 25 The scrollbar automatically requests data as it reaches the bottom
fail False The component needs to know that the request failed, and if true, the prompt is changed
failTips ‘Request failed, try again later! ‘ Information to display for request failure
The principle of

Listens for scrolling, executes the next request when scrolling to user-configured bottom, and does not execute the request when the request is complete. When a request fails, a message indicating component request failure is displayed.

code
<template> <div id="loadMore" class="loadmore" > <slot></slot> <div class="loadmore-tip" id="loadTips" v-if="totalCount > 0 && totalCount >= pageSize" >< I v-show="loadTips==' loadmore-icon '" class="loadmore-icon" ></ I > {{loadTips}} </div> </div> </template> <script> let timer = null // Not acting as a response variable to improve performance export default {props: {pageIndex: {type: Number, default: 1 }, pageSize: { type: Number, default: 10 }, totalCount: { type: Number, default: 0 }, delay: { type: [Number], default: 500}, // The scrollbar will automatically request data. Bottom: {type: [Number], default: 25}, // {type: Boolean, default: false}, failTips: {type: String, default: 'Request failed, try again later! '}}, data () {return {loadTips: 'loading'}; }, watch: { pageIndex () { this.loadMore() }, totalCount: {handler (val, oldval) {if (val > 0) {this.loadMore()}}, // First request immediate: true }, fail (value) { if (value) { this.loadTips = this.failTips } } }, methods: LoadMore () {this.loadTips = 'loading '; const {pageSize, pageIndex, totalCount} = this return new Promise((resolve, reject) => { window.onscroll = () => { timer = setTimeout(() => { if (! document.getElementById('loadTips')) return const clientHeight = document.documentElement.clientHeight || document.body.clientHeight || 0 const rectBottom = document.getElementById('loadTips').getBoundingClientRect().bottom ||  0 if (rectBottom < clientHeight + this.bottom) { const size = totalCount - pageIndex * pageSize if (size > 0) { this.$emit('loadmore', PageIndex + 1) resolve(true)} else {this.loadTips = 'no more data' resolve(false)} clearTimeout(timer)}}, this.delay) } }) } }, beforeDestroy () { clearTimeout(timer) } }; </script> <style lang="scss" scoped> .loadmore-tip { color: #aaa; font-size: 12px; text-align: center; height: 40px; line-height: 40px; } @keyframes rotate-loading { 0% { -webkit-transform: rotate(0); transform: rotate(0); } 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } } @-webkit-keyframes rotate-loading { 0% { -webkit-transform: rotate(0); transform: rotate(0); } 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } } .loadmore-icon { vertical-align: -2px; width: 12px; height: 12px; display: inline-block; background: url("data:image/png; base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAMAAAC5zwKfAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAGzUExURUxpcaSmo6Smo6Smo6Smo 6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo 6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo 6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo 6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo 6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo7OajWMAAACQdFJOUwDzVSjxAgf0ChUBCd/hpyn6+ ai70Qz1uB92XuuOR5xNbnBc0ulZd4eNIdsW/myUA1iBhMgnbQiWb7zsJM/l1hqqFEjOqQ3GrbH4LGQrr/CK49NdjIncrLNiaRtbtRl1771FUHjQj0aQBt5ax WCTHeRmt57dnbTyg6vV7eIgEk4mUdcwOvceDgQRiPylmZgL2vNJv00AAAM1SURBVFjDrZl3WxpBEMaPQ3ovKiAKSreABREVLLEbTewaY4mJJb333nvhIwd2j qNzbeYvHnb2d+zd7Du3LxRVPyaPeqK2Mb8sY3n5yG6L9hxNUuJD7Tk57s6URffxiUcthqZoNaoyNUJlbFUIxDW26zN1Q9/eKACnO2jJcEaLU8eX12sontiUm u5P7tD0TrJ/OtVUPGLo5YVzPChMaZhPLmqLB7WL3vmGwnizg5vXweab9+iqi9LRe2b2ih0cuMRj9km6d2un7brZCniYqMfrmmXSLBua+lfWbFiY1Nmu2lmRT SZpOM59b+LDTPJmpFaKKQ0ZMhe/anDJID9tqj4+ugLjq3K+9SVfhRkro1XvSieMWgXsVJ0R5nRWuePXB2AsrBWyRbXrMGtAWTHUBiN9QkWkD+a1VdQzfD8kX JaGYGZZhTtgf8zFhANjW7BnSndhM/nSJ0o51T7Y1yX6AvUnF6fscqjHQNE1QK9clMhwgZoV1ueE/Sa++zwhACer90SfF+TigZHPOcJIvisMEv5FCf2RChHEI NPfbhCl10gBaog+6qEXthK6m5IU7ixi4hN8JhvcPC4NOH4Y/pKvGfJr5yiJ8Y39dJWs+C2FFn9yvAtKPOC/HHACj9dFVnweD3iOAE14wGukqhV4QCL9djwed YV0OkTghxwwhAj054BBRODTHPASIpBUzWVEoAUbOIK9ZD32Q/Fhlw16YaNvPXRxQJcvdIGlOpFbAPUbu0lBG/XgAf+SRr+FuGYrxqtIZeG48YAKog+qSTwiw gtnmQVCNHEhjkeEl3YbHpA5VqzhEQOSDj7VAo5mdjUa8DUcHp/H0Ihroo+3dVuBiAN4zVAyFsG6FouYNzGMCSzi6D0g+tCqx/RKmBHEHXdfMO6T7R2PIy2fT vnmVt5MC3GZaT8sqe98nvUd1u4L79dO2w9n+8bPX1/5LPv9IWtIbtNVe6GS3mYMyQNeN9LRXGSZLnuXSi3TJe9ywTJNf+SpPSWmrmrK+sx7m755P9hvnSqxt g0Bvk9b5+RjOwd1AgpohtsYnxHaC3Gte+gMnjN75Z8L9jOPFB3WnJK/P7I/VuUfs0V7TrncmP8jtvO4FdRBjgAAAABJRU5ErkJggg==") no-repeat; background-size: 12px 12px; -webkit-animation: rotate-loading 0.5s linear forward infinite; Animation: rotate-loading 0.5s Linear forward infinite; } </style>Copy the code