滚动到底部加载更多
# 触发条件
scrollTop = 0
loadMore() {
const customHeight = 200
let el = this.$refs.movie.$el // 这里 movie 为一个vue组件 所以需要.$el获取dom
let scrollTop = el.scrollTop
let height = el.offsetHeight
let scrollHeight = el.scrollHeight
console.log('scrollHeight', scrollHeight)
console.log('height', height)
console.log('scrollTop', scrollTop)
if (scrollTop + customHeight + height > scrollHeight && scrollTop > this.scrollTop) {
// 距离底部还剩200px了 请求下一段数据
console.log('trigger', scrollTop + customHeight + height - scrollHeight)
this.pagination.pageNum = this.pagination.pageNum + 1
this.getList(true)
}
this.scrollTop = scrollTop
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
注意这个获取的是滚动部分的父盒子的 $el
# scrollHeight
scrollHeight 表示盒子里面 内容的高度
其它盒子位置属性图
当 scrollTop + height === scrollHeight 时, 就表示滚到底了
为了提前触发, 设置了 200px 的补偿 customHeight, 也就是滚动到了离页面底部 200px 的地方 就判定为滚到底了
还有一个问题:需要区分滚动方向, 只有向下滚动才能触发
这里记录了一个 top 值, 每次滚动触发时,用当前的 top 值和上一次的对比, 如果减小就不触发。
# 滚动事件监听
import throttle from 'lodash/throttle'
mounted() {
this.initScroll()
}
initScroll() {
document.addEventListener('scroll', this.fetchData, true)
// 组件销毁时取消监听
this.$once('hook:beforeDestroy', () => {
window.removeEventListener('scroll', this.fetchData)
})
}
fetchData = throttle(() => { // 节流处理
this.loadMore()
}, 300)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
触发后的逻辑
pagination: any = {
pageNum: 1,
pageSize: 40
}
getList(addTo: boolean = false) {
this.getMovieListLoading = true
getMovieList({ params: { ...this.pagination } })
.then(({ data, code, message }: any) => {
if (code === '000000') {
if (addTo) {
if (!data.list || data.list.length === 0) { // 新的数据为空 表示已经到底了
this.$message.warning('到底了')
} else {
this.list = [...this.list, ...(data.list || [])] // 在以前的数据尾部追加新的数据
}
} else {
this.list = data.list || [] // 如果不是追加 那就直接赋值list
}
}
})
.finally(() => {
this.getMovieListLoading = false
})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
html 部分
<transition-group
name="movie-list"
class="movie-list"
style="width: 100%"
ref="movie"
>
<div
class="movie__item"
:class="{ 'is-hover': hoverIndex === i }"
v-for="(item, i) in list"
:key="item._id"
@click="onShowDetail(item)"
@mouseenter="onHover(i)"
>
<div class="movie-card" :style="{ background: getBackgroundUrl(item) }">
<div class="movie-poster" :style="{ '--bgUrl': getBackgroundUrl(item) }">
<div class="action">
<a-icon
class="like"
@click.stop="onLike"
type="heart"
style="margin-right: 12px"
/>
<a-icon class="delete" @click.stop="onDelete(item)" type="delete" />
</div>
</div>
</div>
<div class="movie-name">{{ item.name }}</div>
</div>
</transition-group>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 最终效果
上次更新: 2023/04/05, 09:41:10