摘要:項(xiàng)目中遇到切換列表,每個(gè)都需要分頁的需求,分頁流程具有相似性,于是想將分頁封裝為組件,方便應(yīng)用。組件的復(fù)用完成了以上組件,在對其他分頁的頁面,可以直接復(fù)用。
項(xiàng)目中遇到 tab切換列表,每個(gè)tab都需要分頁的需求,分頁流程具有相似性,于是想將分頁封裝為組件,方便應(yīng)用。
組件的應(yīng)用已寫成一個(gè)小demo,效果如下圖所示(數(shù)據(jù)用mock模擬):
源碼可以查看:wxapp-pagination
項(xiàng)目需求具體項(xiàng)目需求:
查看自己相關(guān)的會(huì)議(頁面命名為 meetings)
tab切換,分為:
“我的會(huì)議”(我參加的會(huì)議,后面會(huì)以 "join" 為 key區(qū)分)
“我的預(yù)約”(我預(yù)約的會(huì)議,后面會(huì)以 "book" 為 key區(qū)分)
一次加載10條(size=10),拉到底部后,加載下一頁(page = page +1)
當(dāng)然,作為前端,要考慮性能方面的需求:
首次只加載默認(rèn)tab頁的首頁,其他tab等到點(diǎn)擊到對應(yīng)tab才開始加載。
回到已加載過的tab頁,保留原數(shù)據(jù)不重新加載。
所以原型圖大概就長這樣:
與分頁邏輯相關(guān)的項(xiàng)目結(jié)構(gòu)如下:
├── components │ ├── meeting-item # 列表item │ └── pagination # 分頁組件 ├── model │ └── user.js # 我的相關(guān) model └── pages │ └── user # 我的相關(guān)頁面 │ ├── meetings # 我的會(huì)議(就是tab要分頁的頁面啦) │ └── ... │ └── vant-weapp
還是用圖理一下他們之間的關(guān)系吧:
在組件內(nèi)監(jiān)聽觸發(fā)分頁事件觸發(fā)分頁的事件是滾動(dòng)到頁面的底部,小程序中,觸發(fā)該事件是Page頁面的onReachBottom事件,但是這個(gè)事件只能在Page中觸發(fā),所以要將這個(gè)觸發(fā)時(shí)機(jī)傳遞給pagination組件。
解決思路是:組件?pagination 內(nèi),設(shè)置key屬性,每當(dāng)onReachBottom事件觸發(fā)之后,設(shè)置組件屬性 key? 為一個(gè)隨機(jī)字符串,當(dāng)組件?pagination?監(jiān)聽到key的變化的時(shí)候,做出分頁操作。
// components/pagination/index.js Component({ properties: { key: { type: String, observer: "_loadMoreData" // _loadMoreData 為分頁操作 } } })
Page({ onReachBottom(){ const key = scene[+this.data.currentTab].key // 對應(yīng)tab對應(yīng)key this.setData({ [key]: random(16) }) } })分頁組件的實(shí)現(xiàn)邏輯
觸發(fā)到達(dá)底部之后,需要加載數(shù)據(jù)。但再加載之前,先滿足加載的條件:
上一頁還未加載完成(loading = true),不重復(fù)加載
當(dāng)前頁面全部加載完(ended = true),不繼續(xù)加載
具體加載流程為:
page:觸發(fā) onReachBottom 事件,修改 pagination組件 key 值
component:?key值監(jiān)聽到變化,觸發(fā)加載事件?_loadMoreData
component: _loadMoreData 中判斷滿足條件后,觸發(fā)加載列表函數(shù) this.triggerEvent("getList"),并傳入頁面參數(shù)page 和 size。
page:向model層獲取數(shù)據(jù)。
page:獲取數(shù)據(jù)后,傳遞給 pagination組件list和total 值。
component:list 監(jiān)聽到變化,判斷是否加載完成。
component// components/pagination/index.js Component({ properties: { name: String, key: { type: String, observer: "_loadMoreData" // _loadMoreData 為分頁操作 }, size: { // 每次加載條目數(shù) type: Number, value: 10 }, total: Number, // 頁面總數(shù) list: { // 已加載條目 type: Array, observer: "_endState" // 每次加載完新數(shù)據(jù),判斷數(shù)據(jù)是否全部加載完成 } }, data: { page: 0, // 當(dāng)前第幾頁 loading: false, // 是否正在加載 ended: false // 數(shù)據(jù)是否已全部加載完成 }, methods: { _loadMoreData(){ const { loading, ended, size } = this.data if (loading) return // 上一頁還未加載完成,不加載 if (ended) return // 當(dāng)前頁面全部加載完,不加載 const page = this.data.page + 1 this.setData({ loading: true, // 開始加載新頁面loading設(shè)置為true page }) // 觸發(fā)加載下一頁,并傳入?yún)?shù) this.triggerEvent("getList", { page, size }) }, _endState(val, oldVal) { const { total, list } = this.properties let ended = false // 判斷數(shù)據(jù)是否全部加載完成 if (list.length >= total) { ended = true } this.setData({ loading: false, // 當(dāng)前頁面加載完成,loading設(shè)置為false ended }) } } })page
循環(huán)列表item
pagination組件獲取了可循環(huán)的列表,初始想法是循環(huán)slot,但是在slot中卻獲取不到 item 對象:
解決的辦法是將每個(gè)列表項(xiàng)封裝為組件,循環(huán)抽象節(jié)點(diǎn),這樣對其他頁面的分頁具有可拓展性。
componentGenerics?字段中聲明:
// components/pagination/index.json { "componentGenerics": { "selectable": true }, // ... }
使用抽象節(jié)點(diǎn):
指定“selectable”具體是哪個(gè)組件:
對應(yīng) json 文件定義對應(yīng)?usingComponents?:
// pages/user/meetings/index.json { "usingComponents": { "pagination":"/components/pagination/index", "meeting-item":"/components/meeting-item/index" } }
meeting-item 組件接收一個(gè)屬性 item,這樣在?meeting-item 組件中,就可以獲取到循環(huán)列表的item值,并正常繪制頁面。
實(shí)現(xiàn)切換懶加載給pagination添加initImmediately屬性,當(dāng)initImmediately為true時(shí),首次加載頁面,并用變量?initState標(biāo)記是否已經(jīng)初始化頁面過。
// components/pagination/index.js Component({ properties: { initImmediately: { type: Boolean, value: true, observer: function(val){ if (val && !this.data.initState) { this.initData() } } }, // ... }, data: { initState: false, // 是否已經(jīng)加載過 // ... }, lifetimes: { attached: function () { if (this.data.initImmediately){ this.initData() } }, }, methods: { initData(){ console.info(`${this.data.name}:start init data`) this._loadMoreData() this.setData({ initState: true }) }, // ... _endState(val, oldVal) { if (!this.data.initState) return // ... }, } })
當(dāng)currentTab為當(dāng)前類型的時(shí)候,initImmediately 設(shè)置為 true。
組件的復(fù)用
完成了以上組件,在對其他分頁的頁面,可以直接復(fù)用。比如,實(shí)現(xiàn)一個(gè)獲取全部用戶列表的分頁,只需要新增一個(gè)user-item的組件,像這樣調(diào)用:
具體應(yīng)用可以查看我寫的小demo:wxapp-pagination。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/105739.html
摘要:基礎(chǔ)布局的中主要為部分,分別是用于搜索篩選和分頁的表單控件用于排序表格的表頭以及用于展示數(shù)據(jù)的。這也是前瞻發(fā)布之后,提出廢棄部分功能后許多人反應(yīng)較為強(qiáng)烈的原因。 與上周的第一篇實(shí)踐教程一樣,在這篇文章中,我將繼續(xù)從一種常見的功能——表格入手,展示Vue.js中的一些優(yōu)雅特性。同時(shí)也將對filter功能與computed屬性進(jìn)行對比,說明各自的適用場景,也為vue2.0版本中即將刪除的部...
摘要:基礎(chǔ)布局的中主要為部分,分別是用于搜索篩選和分頁的表單控件用于排序表格的表頭以及用于展示數(shù)據(jù)的。這也是前瞻發(fā)布之后,提出廢棄部分功能后許多人反應(yīng)較為強(qiáng)烈的原因。 與上周的第一篇實(shí)踐教程一樣,在這篇文章中,我將繼續(xù)從一種常見的功能——表格入手,展示Vue.js中的一些優(yōu)雅特性。同時(shí)也將對filter功能與computed屬性進(jìn)行對比,說明各自的適用場景,也為vue2.0版本中即將刪除的部...
摘要:分鐘學(xué)是一個(gè)系列,簡單暴力,包學(xué)包會(huì)。一旦組件掛載后,會(huì)自動(dòng)進(jìn)行數(shù)據(jù)請求,前提是客戶端提供的和后端的相符。如果回調(diào)返回直接不作請求。在組件內(nèi)進(jìn)行分頁請求之前提到了,這個(gè)裝飾器為添加了對象,其中有個(gè)函數(shù)為。 21 分鐘學(xué) apollo-client 是一個(gè)系列,簡單暴力,包學(xué)包會(huì)。 搭建 Apollo client 端,集成 redux使用 apollo-client 來獲取數(shù)據(jù)修改本...
摘要:一開始,公司推出的,包括了規(guī)范以及其配套構(gòu)建工具。代表的不同狀態(tài)或不同版本。再來看一個(gè)之前用常規(guī)方式命名的的例子這些類名真是太不精確了,并不能告訴我們足夠的信息。 這段時(shí)間在整理前端部分的代碼規(guī)范,前面提到的CSS規(guī)范里面會(huì)涉及到選擇器的命名,就參考BEM的命名規(guī)范,內(nèi)容整理如下,供大家參考,請斧正!如大家有興趣,可移步至CSS編碼規(guī)范 BEM是由Yandex公司推出的一套CSS命名...
摘要:本項(xiàng)目將使用配合最簡單的邏輯來展示一個(gè)基于的微服務(wù)全??焖匍_發(fā)實(shí)踐的。提供一系列大型項(xiàng)目常用的非功能性特征,比如內(nèi)嵌服務(wù)器,安全,指標(biāo),健康檢測,外部化配置。 SprintBoot-Vue SpringBoot + 前端MVVM 基于Java的微服務(wù)全??焖匍_發(fā)實(shí)踐 showImg(https://segmentfault.com/img/remote/1460000010167913...
閱讀 1141·2021-08-12 13:24
閱讀 2989·2019-08-30 14:16
閱讀 3315·2019-08-30 13:01
閱讀 2077·2019-08-30 11:03
閱讀 2779·2019-08-28 17:53
閱讀 3092·2019-08-26 13:50
閱讀 2273·2019-08-26 12:00
閱讀 953·2019-08-26 10:38