Vue 触底加载组件简单实现

  • Post author:
  • Post category:vue


今天写了个触底加载的组件,因为经常用到,之前总会遇到一种需求,就是有一个列表,可以实现下拉刷新,上拉加载,

找了一个一个的插件,填了一个一个的坑后,决定自己写个触底加载,简单实现下这个功能,不要跟我说:“这样不好看,我们要看

有橡皮筋那样的弹性效果,还要有下拉刷新,巴拉巴拉。。。。”,写过几次这种需求的我,已经不在乎这种效果了,丫的全是坑,

一句“可以,但没必要”,就完了。

废话说多了,来看下实现触底加载的几个步骤

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 ,用则写,不用就不管了

转载于:https://www.cnblogs.com/blackbentel/p/11065611.html