找到一個好用的下拉刷新,上拉加載的vue 插件 vue-scroller, git 地址
return
今天寫了個觸底加載的組件,因為經常用到,之前總會遇到一種需求,就是有一個列表,可以實現下拉刷新,上拉加載,
找了一個一個的插件,填了一個一個的坑后,決定自己寫個觸底加載,簡單實現下這個功能,不要跟我說:“這樣不好看,我們要看
有橡皮筋那樣的彈性效果,還要有下拉刷新,巴拉巴拉。。。。”,寫過幾次這種需求的我,已經不在乎這種效果了,丫的全是坑,
一句“可以,但沒必要”,就完了。
廢話說多了,來看下實現觸底加載的幾個步驟
1. 觸底加載的布局,一個高度固定的容器,然后容器里面放一個列表,一般列表的初始高度是大於容器的高度,小於的話它滾動不了,就監聽不到
它有沒有滾到底部了。注意: 容器高度取 clientHeight ,列表高度取 offsetHeight
2. 監聽容器的滾動事件,在滾動時獲取滾出容器的高度,當滾出的高度加上容器的高度等於列表的高度時就觸底了。觸底加載的組件就這些邏輯了
上觸底加載組件代碼
1 <template> 2 <div class="infinite" ref="container" :style="{height: height}"> 3 <div class="inner" ref="inner"> 4 <!-- 列表標題 --> 5 <slot name="title"></slot> 6 <!-- 這里放列表 --> 7 <slot></slot> 8 <!-- 加載中的動畫 --> 9 <slot name="loading" v-if="loading"></slot> 10 <!-- 加載完成的動畫 --> 11 <slot name="nomore" v-if="nomore"></slot> 12 </div> 13 </div> 14 </template> 15 <script> 16 export default { 17 name: 'infinite-scroll', 18 props: { 19 height: { 20 type: String, 21 default: '100%' 22 }, 23 loading: { 24 type: Boolean, 25 default: false 26 }, 27 nomore: { 28 type: Boolean, 29 default: false 30 }, 31 }, 32 data () { 33 return { 34 containerHeight: 0, 35 innerHeight: 0 36 } 37 }, 38 created () { 39 40 }, 41 mounted () { 42 this.containerHeight = this.$refs.container.clientHeight 43 this.innerHeight = this.$refs.inner.offsetHeight 44 this.$refs.container.addEventListener('scroll', this.initScroll) 45 }, 46 methods: { 47 initScroll (e) { 48 if (this.loading || this.nomore) return 49 this.innerHeight = this.$refs.inner.offsetHeight 50 let scrollTop = e.target.scrollTop 51 if (scrollTop + this.containerHeight >= this.innerHeight) { 52 console.log('-----------------觸底了-------------'); 53 this.$emit('loadBottom') 54 } 55 } 56 } 57 } 58 </script> 59 <style lang="less" scoped> 60 .infinite { 61 width: 100%; 62 background-color: skyblue; 63 overflow: auto; 64 -webkit-overflow-scrolling: touch; // 解決iOS滾動問題 65 } 66 </style>
然后在頁面中使用這個組件,我把組件注冊成全局組件了,所以直接就用在頁面了
1 <template> 2 <div class="home"> 3 <div class="scroll"> 4 <infinite-scroll class="infinite" :loading="loading" :nomore="nomore" @loadBottom="loadmore" > 5 <template slot="title"> 6 <p>這是一個標題</p> 7 </template> 8 <p v-for="item in list" :key="item.id">{{ item.name + '---' + item.value }}</p> 9 <template slot="loading" > 10 <i>加載中</i> 11 </template> 12 <template slot="nomore"> 13 <i>沒有更多了</i> 14 </template> 15 </infinite-scroll> 16 </div> 17 </div> 18 </template> 19 <script> 20 export default { 21 data () { 22 return { 23 loading: false, 24 pageSize: 10, 25 pageNumber: 1, 26 total: 0, 27 loadTotal: false, 28 list: [] 29 } 30 }, 31 created () { 32 this.loadmore() 33 }, 34 methods: { 35 async loadmore () { 36 if (this.loading || this.nomore) return 37 this.loading = true 38 const response = await this.$post('******', { 39 pageSize: this.pageSize, 40 pageNumber: this.pageNumber 41 }) 42 if ('請求成功') { 43 this.total = response.totalRecord 44 this.list.push(...response.list) 45 if (this.list.length >= this.total) { 46 this.nomore = true 47 } else { 48 this.pageNumber ++ 49 } 50 } 51 this.$nextTick(() => { 52 setTimeout(() => { 53 this.loading = false 54 }, 300); 55 }) 56 }, 57 } 58 } 59 </script> 60 <style lang="less" scoped> 61 .home { 62 padding: 1px; 63 .scroll { 64 width: 80%; 65 height: 7rem; 66 margin: 1rem auto; 67 .infinite { 68 font-size: .32rem; 69 line-height: .8rem; 70 overflow: auto; 71 i { 72 font-size: .24rem; 73 text-align: center; 74 width: 100%; 75 display: block; 76 } 77 } 78 } 79 } 80 </style>
組件中有這么幾個參數時必傳的
1. loading 節流的,開始加載時是 true 加載更多的請求完成並顯示在頁面上了改為 false
2. nomore 所有數據是否都已加載完成
3. loadBottom 監聽這個事件,事件觸發后就是要加載更多了
4. 還有一些 slot ,用則寫,不用就不管了