Vue+Vant實(shí)現(xiàn)下拉加載功能
介紹
簡介:為了像微信一樣方便地加載更多歷史消息,我們使用vant組件來實(shí)現(xiàn)下拉加載功能。我們對組件進(jìn)行了改造,將下拉刷新變成了下拉加載更多的形式。這樣,用戶只需要在第一次下拉時手動開啟加載更多,之后只需將頁面滑動到頂部,加載更多就會自動觸發(fā),直到無數(shù)據(jù)可加載時,會顯示“無更多數(shù)據(jù)”的提示。
目標(biāo):如同微信那般,下拉加載更多歷史消息。
組件:利用vant組件的下拉刷新組件。
效果:用戶只需在第一次下拉時手動開啟加載更多,之后到達(dá)頂部時會自動觸發(fā)加載更多,直到所有數(shù)據(jù)都加載完畢,此時會出現(xiàn)提示信息:“無更多數(shù)據(jù)”。
目的:是為了讓用戶在使用過程中更加方便快捷地加載歷史消息,提高用戶體驗(yàn)。
該組件官方地址:vant-contrib.gitee.io/vant/v2/#/zh-CN/pull-refresh
效果
我寫了一個new promise,延遲了1s返回數(shù)據(jù)。
開始
引入
import { PullRefresh } from "vant"; export default { components: { "van-pull-refresh": PullRefresh }, }
template上的使用
<div class="refresh"> <van-pull-refresh v-model="isRefreshLoading" pulling-text="下拉加載數(shù)據(jù)" loosing-text="釋放即可刷新" :success-text="isRefreshDisabled ? '無更多數(shù)據(jù)' : ''" :success-duration="800" :disabled="isRefreshDisabled" @refresh="onRefresh" > <div ref="courseListHeight"> <div v-for="(item, index) in videoList" :key="index" class="content"> {{ item.video_id }} </div> </div> </van-pull-refresh> </div>
使用的參數(shù)
我就怕大家懶得打開
Props
參數(shù) | 說明 | 類型 | 默認(rèn)值 |
---|---|---|---|
v-model | 是否處于加載中狀態(tài) | boolean | - |
pulling-text | 下拉過程提示文案 | string | 下拉即可刷新... |
loosing-text | 釋放過程提示文案 | string | 釋放即可刷新... |
success-text | 刷新成功提示文案 | string | - |
success-duration | 刷新成功提示展示時長(ms) | number / string | 500 |
disabled | 是否禁用下拉刷新 | boolean | false |
Events
事件名 | 說明 | 回調(diào)參數(shù) |
---|---|---|
refresh | 下拉刷新時觸發(fā) | - |
數(shù)據(jù)處理
處理方案:
1、利用getBoundingClientRect
監(jiān)聽滑塊到指定的區(qū)域之后,滿足判斷條件,開始請求下一頁數(shù)據(jù)。
2、阻止在規(guī)定的區(qū)域內(nèi),多次調(diào)用api.
3、利用渲染可知高度,使用scrollTo/scrollBy滾動到下拉加載的數(shù)據(jù)處。
4、請求數(shù)據(jù)結(jié)束,關(guān)閉加載中狀態(tài)以及禁用下拉刷新。
data的數(shù)據(jù)
params: { page_size: 5, page_num: 1, }, isRefreshLoading: false, // 是否處于加載中狀態(tài) isRefreshDisabled: false, // 是否禁用下拉刷新 videoList: [], // 數(shù)據(jù)內(nèi)容 courseListPageHeight: 0, // 頁面的高度 domVantRefreh: "", // 獲取van-loading到頂部的高度 lockOneApiState: false // 防止反復(fù)的請求api
再初次進(jìn)頁面需要請求一次接口
beforeMount() { this.getapi(); },
下面就是對后面的數(shù)據(jù)進(jìn)行請求,在methods中
onRefresh() { // 獲取van-loading到頂部的高度 this.domVantRefreh = document.querySelector(".van-loading"); // 加載監(jiān)聽scroll滾動事件 window.addEventListener("scroll", this.loadingPage); this.params.page_num++; this.getapi(); }, getapi() { getAnchorEnjoySection({ ...this.params }).then(res => { if (res.code == 200) { // 第一次添加數(shù)據(jù) if (this.params.page_num == 1) { this.videoList = res.result.video_list; this.$nextTick(() => { // 渲染完成,開始滾動到最低處 window.scrollBy(0, 9999); // 獲取第一次的頁面列表的高 this.courseListPageHeight = this.$refs.courseListHeight.clientHeight; }); } else { this.videoList.unshift(...(res.result.video_list)); } // 對后面的數(shù)據(jù)進(jìn)行處理 if (res.result.video_list.length !== 0 && this.params.page_num !== 1) { this.isRefreshDisabled = false; this.$nextTick(() => { // 獲取到需要滾動的高 let heightElement = this.$refs.courseListHeight.clientHeight - this.courseListPageHeight; this.courseListPageHeight = this.$refs.courseListHeight.clientHeight; window.scrollBy(0, heightElement); }); } // 請求無數(shù)據(jù)的時候 if (res.result.video_list.length == 0) { this.isRefreshDisabled = true; //無數(shù)據(jù)了,不需要再下拉刷新了 this.isRefreshLoading = false; // 加載狀態(tài)取消 window.removeEventListener('scroll', this.loadingPage); // 取消監(jiān)聽 } } this.lockOneApiState = true; // 鎖狀態(tài)打開 }); }, loadingPage() { // 由于我們給與了margin-top: 20px;有20的高度,所以使用 0 恰到好處,能再快看到加載狀態(tài)的時候,進(jìn)行了加載,同時需要:鎖的狀態(tài)是打開的,并且沒有禁用下拉刷新 if (this.domVantRefreh.getBoundingClientRect().top >= 0 && this.lockOneApiState == true && this.isRefreshDisabled == false) { this.params.page_num++; this.getapi(); this.lockOneApiState = false; } }
完整代碼
我使用cnd.js
引入總有點(diǎn)小問題,就直接貼出來了,以后解決來再替換。
<template> <div class="refresh"> <van-pull-refresh v-model="isRefreshLoading" pulling-text="下拉加載數(shù)據(jù)" loosing-text="釋放即可刷新" :success-text="isRefreshDisabled ? '無更多數(shù)據(jù)' : ''" :success-duration="800" :disabled="isRefreshDisabled" @refresh="onRefresh" > <div ref="courseListHeight"> <div v-for="(item, index) in videoList" :key="index" class="content"> {{ item }} </div> </div> </van-pull-refresh> </div> </template> <script> import { PullRefresh } from "vant"; export default { components: { "van-pull-refresh": PullRefresh }, data() { return { dataList: [111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135], params: { page_size: 5, page_num: 1 }, isRefreshLoading: false, // 是否處于加載中狀態(tài) isRefreshDisabled: false, // 是否禁用下拉刷新 videoList: [], // 數(shù)據(jù)內(nèi)容 courseListPageHeight: 0, // 頁面的高度 domVantRefreh: "", // 獲取van-loading到頂部的高度 lockOneApiState: false // 防止反復(fù)的請求api }; }, beforeMount() { this.getapi(); }, methods: { onRefresh() { // 獲取van-loading到頂部的高度 this.domVantRefreh = document.querySelector(".van-loading"); window.addEventListener("scroll", this.loadingPage); this.params.page_num++; this.getapi(); }, getapi() { this.getDataList(this.params).then(res => { console.log(res); if (res.code == 200) { // 第一次添加數(shù)據(jù) if (this.params.page_num == 1) { this.videoList = res.result.video_list; this.$nextTick(() => { window.scrollBy(0, 9999); this.courseListPageHeight = this.$refs.courseListHeight.clientHeight; }); } else { this.videoList.unshift(...(res.result.video_list)); } // 對后面的數(shù)據(jù)進(jìn)行處理 if (res.result.video_list.length !== 0 && this.params.page_num !== 1) { this.isRefreshDisabled = false; this.$nextTick(() => { let heightElement = this.$refs.courseListHeight.clientHeight - this.courseListPageHeight; this.courseListPageHeight = this.$refs.courseListHeight.clientHeight; window.scrollBy(0, heightElement); }); } // 請求無數(shù)據(jù)的時候 if (res.result.video_list.length == 0) { this.isRefreshDisabled = true; this.isRefreshLoading = false; window.removeEventListener('scroll', this.loadingPage); } } this.lockOneApiState = true; }); }, loadingPage() { // 由于我們給與了margin-top: 20px;有20的高度,所以使用 0 恰到好處,能再快看到加載狀態(tài)的時候,進(jìn)行了加載 if (this.domVantRefreh.getBoundingClientRect().top >= 0 && this.lockOneApiState == true && this.isRefreshDisabled == false) { this.params.page_num++; this.getapi(); this.lockOneApiState = false; } }, // 偽裝數(shù)據(jù)請求 getDataList(params) { return new Promise( resolve => { let result = { code: 200, result: { video_list: this.dataList.splice(1 * params.page_num - 1, params.page_size) } }; setTimeout(() => { resolve(result); }, 1000); } ); } } }; </script> <style lang="scss" scoped> .refresh { padding: 0 20px 20px 20px; .content{ width: 100%; height: 320px; text-align: center; margin-top: 20px; background-color: cadetblue; font-size: 22px; } } </style>
到此這篇關(guān)于Vue+Vant實(shí)現(xiàn)下拉加載功能的文章就介紹到這了,更多相關(guān)Vue Vant下拉加載內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue導(dǎo)入新工程?“node_modules依賴”問題
這篇文章主要介紹了vue導(dǎo)入新工程?“node_modules依賴”問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09vue里使用create,mounted調(diào)用方法的正確姿勢說明
這篇文章主要介紹了vue里使用create,mounted調(diào)用方法的正確姿勢,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-04-04vue如何修改el-form-item中的label樣式修改問題
這篇文章主要介紹了vue如何修改el-form-item中的label樣式修改問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10詳解使用jest對vue項(xiàng)目進(jìn)行單元測試
這篇文章主要介紹了詳解使用jest對vue項(xiàng)目進(jìn)行單元測試,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-09-09VUE項(xiàng)目運(yùn)行失敗原因及解決辦法圖解(以vscode為例)
記錄一下踩坑,前幾天從同事手上接手了一個Vue的項(xiàng)目,下面這篇文章主要給大家介紹了關(guān)于VUE項(xiàng)目運(yùn)行失敗原因及解決辦法的相關(guān)資料,本文以vscode為例,需要的朋友可以參考下2023-06-06Vue實(shí)現(xiàn)動態(tài)圓環(huán)百分比進(jìn)度條
這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)動態(tài)圓環(huán)百分比進(jìn)度條,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09Vue封裝localStorage設(shè)置過期時間的示例詳解
這篇文章主要介紹了Vue封裝localStorage設(shè)置過期時間的相關(guān)資料,在這個示例中,我們在MyComponent.vue組件的setup函數(shù)中導(dǎo)入了setItemWithExpiry和getItemWithExpiry函數(shù),并在函數(shù)內(nèi)部使用它們來設(shè)置和獲取帶有過期時間的localStorage數(shù)據(jù),需要的朋友可以參考下2024-06-06