麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 課堂 > 小程序 > 正文

小程序分頁實(shí)踐之編寫可復(fù)用分頁組件

2020-03-21 15:51:20
字體:
供稿:網(wǎng)友

項(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)擊到對(duì)應(yīng)tab才開始加載。
  • 回到已加載過的tab頁,保留原數(shù)據(jù)不重新加載。

所以原型圖大概就長這樣:

小程序,分頁,分頁組件

邏輯實(shí)現(xiàn)

與分頁邏輯相關(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.jsComponent({ properties: {  key: {   type: String,   observer: '_loadMoreData' // _loadMoreData 為分頁操作  } }})
<!-- pages/user/meetings/index.wxml --><tabs active="{{currentTab}}" bind:change="onChange">  <tab   <view class="meeting-list">     <pagination       name="JOIN"      key="{{joinKey}}"      >     </pagination>   </view>  </tab>  <tab   <view class="meeting-list">    <pagination      name="BOOK"     key="{{bookKey}}"    >    </pagination>   </view>  </tab></tabs>
Page({ onReachBottom(){  const key = scene[+this.data.currentTab].key // 對(duì)應(yīng)tab對(duì)應(yīng)key  this.setData({   [key]: random(16)  }) }})

分頁組件的實(shí)現(xiàn)邏輯

觸發(fā)到達(dá)底部之后,需要加載數(shù)據(jù)。但再加載之前,先滿足加載的條件:

  • 上一頁還未加載完成(loading = true),不重復(fù)加載
  • 當(dāng)前頁面全部加載完(ended = true),不繼續(xù)加載

具體加載流程為:

  1. page:觸發(fā) onReachBottom 事件,修改 pagination組件 key 值
  2. component: key值監(jiān)聽到變化,觸發(fā)加載事件 _loadMoreData
  3. component: _loadMoreData 中判斷滿足條件后,觸發(fā)加載列表函數(shù) this.triggerEvent('getList'),并傳入頁面參數(shù)page 和 size。
  4. page:向model層獲取數(shù)據(jù)。
  5. page:獲取數(shù)據(jù)后,傳遞給 pagination組件list和total 值。
  6. component:list 監(jiān)聽到變化,判斷是否加載完成。

component

// components/pagination/index.jsComponent({ 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

<!-- pages/user/meetings/index.wxml --><pagination  name="BOOK" key="{{bookKey}}" bind:getList="getBookMeetings" list="{{bookMeetings}}" total="{{bookTotal}}"></pagination>

循環(huán)列表item

pagination組件獲取了可循環(huán)的列表,初始想法是循環(huán)slot,但是在slot中卻獲取不到 item 對(duì)象:

<view wx:for="{{list}}" wx:for-item="item" wx:key="index"> <slot></slot></view>

解決的辦法是將每個(gè)列表項(xiàng)封裝為組件,循環(huán)抽象節(jié)點(diǎn),這樣對(duì)其他頁面的分頁具有可拓展性。

componentGenerics 字段中聲明:

// components/pagination/index.json{ "componentGenerics": {  "selectable": true }, // ...}

使用抽象節(jié)點(diǎn):

<!-- components/pagination/index.wxml --><view wx:for="{{list}}" wx:for-item="item" wx:key="index">  <selectable item="{{item}}"></selectable></view>

指定“selectable”具體是哪個(gè)組件:

<!-- pages/user/meetings/index.wxml --><pagination  generic:selectable="meeting-item"  // ... 其他屬性></pagination>

對(duì)應(yīng) json 文件定義對(duì)應(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.jsComponent({ 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。

<!-- pages/user/meetings/index.wxml --><pagination   name="JOIN"  init-immediately="{{currentTab==type['JOIN']}}"  // ...></pagination><pagination   name="BOOK"  init-immediately="{{currentTab==type['BOOK']}}"  // ...></pagination>

組件的復(fù)用

完成了以上組件,在對(duì)其他分頁的頁面,可以直接復(fù)用。比如,實(shí)現(xiàn)一個(gè)獲取全部用戶列表的分頁,只需要新增一個(gè)user-item的組件,像這樣調(diào)用:

<pagination  name="USER" key="{{key}}"  bind:getList="getUserList"  list="{{userList}}"  total="{{userTotal}}" generic:selectable="user-item"></pagination>

具體應(yīng)用可以查看我寫的小demo:wxapp-pagination。

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 羞羞视频免费观看网站 | 国产女厕一区二区三区在线视 | 今井夏帆av一区二区 | 亚洲欧美日韩久久精品第一区 | 日韩黄色片网站 | 欧美精选一区二区 | 可以看逼的视频 | 欧美视频在线一区二区三区 | 黄网免费看 | 国产精品久久久久久久av | a一级黄色毛片 | 中日韩免费视频 | 成人在线视频免费观看 | 国产精品视频一区二区三区四区五区 | 国产一区二区三区视频免费 | 久久久久久久高清 | 日产精品一区二区三区在线观看 | 九九热精品在线视频 | 精品在线观看一区 | 日本黄色一级毛片 | 成年人黄色免费网站 | 在线1区 | 国产精品久久久久久久久久久久久久久 | 免费观看一区二区三区视频 | 依人九九宗合九九九 | free性欧美hd另类 | av免费提供 | 欧美精品激情视频 | 91精品国产综合久久婷婷香蕉 | 亚洲情av| 国产精品99久久久久久久 | 久久精品网站视频 | videos真实高潮xxxx | 久操福利视频 | 日产精品久久久一区二区开放时间 | 国产精品久久久久久久久久久久午夜 | 欧美一级淫片免费播放口 | 成人在线观看地址 | 国产毛片网站 | 99这里精品| 毛片小网站 |