I have been working on mobile h5 pages recently, so I can’t do paging and other things according to the traditional pc pager’s thinking. It’s not convenient to click on such a small screen. Generally speaking, mobile phones are pulling up and loading more, which is in line with normal usage habits.
First, I will simply write the html code for the template part, which is very simple and clear logic:
<template> <div class="loadmore"> <div class="loadmore__body"> <slot></slot> </div> <div class="loadmore__footer"> <span v-if="loading"> <i class="tc-loading"></i> <span>Loading</span> </span> <span v-else-if="loadable">Pull-up load more</span> <span v-else>No more</span> </div> </div> </template>
Then there is the business part
Before writing components manually, clarify the requirements:
Loading the page -> Slide to the bottom -> Pull up a certain distance -> Loading the second page -> Continue with the previous steps -> No more
This is a user interaction logic, and we need to map it to code logic:
The first page is automatically loaded on the first screen -> Slide to the bottom && When pressed, the sliding distance is offset from the Y axis -> Request the backend to load the second page -> Judging whether there is still a next page based on the return field
With code logic, the backbone comes out, and loading and judgment are controlled by events. As a vue component, we need to cooperate with the vue life cycle to mount events and destroy events.
export default { mounted() { // Determine the container // Container binding event }, beforeDestory() { // Unbinding event }, }
If it is not unbinding, every time you load the component, you will bind an event...
Then we need some core event callback methods to load the data rendering page at the appropriate time. Recall that first we need the load function to get the data at http, and then we need three callback functions pointDown(), pointMove(), and pointUp() that bind the event, respectively, corresponding to the user's press, move, and pop up finger operations:
export default { ··· methods:{ /** * Methods to load a set of data */ load() { // Set options this.$(options).then((res) => { // Processing after obtaining data }).catch((e) => { // Exception handling }) }, /** * Mouse pressing the event handler function * @param {Object} e - Event Object */ pointerdown(e) { // Get the pressed position = ? [0].pageY : }, /** * Mouse move event handling function * @param {Object} e - Event Object */ pointermove(e) { const container = this.$container const pageY = ? [0].pageY : const moveY = pageY - // If you have scrolled down to the bottom of the page if (moveY < 0 && ( + ( , , )) >= ) { // Prevent native pull-up drags from exposing the blank area at the bottom of the page (mainly for iOS version of WeChat) () // If the pull-up distance exceeds 50 pixels, then load the next page if (moveY < -50) { = pageY () } } }, /** * Mouse releases event handling function */ pointerup() { // This is to cancel the drag state. You need to be careful not to trigger some event callbacks again during the dragging process, or not to be messy. = false }, }, ··· }
Basically, the backbone has been completed, and some props incoming or some logical control details need to be added to post the source code of the entire component:
<template> <div class="loadmore"> <!-- <div class="loadmore__header"></div> --> <div class="loadmore__body"> <slot></slot> </div> <div class="loadmore__footer"> <span v-if="loading"> <i class="tc-loading"></i> <span>Loading</span> </span> <span v-else-if="loadable">Pull-up load more</span> <span v-else>No more</span> </div> </div> </template> <script type="text/babel"> import axios from 'axios' const CancelToken = export default { data() { return { /** * Total number of pages (returned by the server) * @type {number} */ count: 0, /** * Is it dragging or not * @type {boolean} */ dragging: false, /** * Number of loaded times * @type {number} */ times: 0, /** * Recording has begun * @type {boolean} */ started: false, /** * Loading * @type {boolean} */ loading: false, } }, props: { /** * Automatically start loading of data after initialization */ autoload: { type: Boolean, default: true, }, /** * The scrollable parent element closest to the component (used to listen to events and get scroll bar position) */ container: { // Selector or Element default: 'body', }, /** * Disable components */ disabled: { type: Boolean, default: false, }, /** * Axios request parameter configuration object * {@link /mzabriskie/axios#request-config} */ options: { type: Object, default: null, }, /** * Start page number */ page: { type: Number, default: 1, }, /** * Number of data pieces loaded per page */ rows: { type: Number, default: 10, }, /** * Data loading request address */ url: { type: String, default: '', }, }, computed: { /** * Is it possible to load * @returns {boolean} Yes or no */ loadable() { return ! && (! || ( + ) <= ) }, }, mounted() { let container = if (container) { if (typeof container === 'string') { container = (container) } else if (!) { container = } } if (!container) { container = } this.$container = container = (this) = (this) = (this) if () { ('pointerdown', , false) ('pointermove', , false) ('pointerup', , false) ('pointercancel', , false) } else { ('touchstart', , false) ('touchmove', , false) ('touchend', , false) ('touchcancel', , false) ('mousedown', , false) ('mousemove', , false) ('mouseup', , false) } if () { () } }, // eslint-disable-next-line beforeDestroy() { const container = this.$container if () { ('pointerdown', , false) ('pointermove', , false) ('pointerup', , false) ('pointercancel', , false) } else { ('touchstart', , false) ('touchmove', , false) ('touchend', , false) ('touchcancel', , false) ('mousedown', , false) ('mousemove', , false) ('mouseup', , false) } if ( && ) { () } }, methods: { /** * Methods to load a set of data */ load() { if ( || ) { return } = true = true const params = { currentPage: + , pageSize: , } const options = ({}, , { url: , cancelToken: new CancelToken((cancel) => { = cancel }), }) if (String().toUpperCase() === 'POST') { = ({}, , params) } else { = ({}, , params) } this.$(options).then((res) => { const data = += 1 = false = this.$emit('success', ) this.$emit('complete') }).catch((e) => { = false this.$emit('error', e) this.$emit('complete') }) }, /** * Reset load related variables */ reset() { = 0 = 0 = false = false }, /** *Restart loading */ restart() { () () }, /** * Mouse pressing the event handler function * @param {Object} e - Event Object */ pointerdown(e) { if ( || ! || ) { return } = true = ? [0].pageY : }, /** * Mouse move event handling function * @param {Object} e - Event Object */ pointermove(e) { if (!) { return } const container = this.$container const pageY = ? [0].pageY : const moveY = pageY - // If you have scrolled down to the bottom of the page if (moveY < 0 && ( + ( , , )) >= ) { // Prevent native pull-up drags from exposing the blank area at the bottom of the page (mainly for iOS version of WeChat) () // If the pull-up distance exceeds 50 pixels, then load the next page if (moveY < -50) { = pageY () } } }, /** * Mouse releases event handling function */ pointerup() { = false }, }, } </script>
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.