предисловие
Как определить, что прокрутка достигла дна
Взгляните на некоторые фотографии:
Дело 1:
Когда высота документа все еще больше, чем высота видимой области, прокрутки нет, поэтому нет низа прокрутки.
Второй случай:
Когда высота документа превышает высоту видимой области, остальные документы не прокручиваются, т.е.可视区域高度 + 滚动高度 < 文档高度, условие для катящегося дна в это время не достигается
Случай третий:
Высота документа превышает видимую область и прокручивается до нижней части документа, т. е.可视区域高度 + 滚动高度 = 文档高度
Определить, следует ли прокручивать до конца
Проанализировав три вышеуказанные ситуации, нам нужно получить可视区域的高度 , 滚动高度 , 文档高度Эти три переменные сравниваются.
высота видимой области
function getWindowHeight() {
return document.documentElement.clientHeight;
}
высота прокрутки
Используйте document.documentElement.scrollTop для страниц с объявлением типа документа, особый случай Safari: используйте window.pageYOffset
function getScrollHeight() {
return Math.max(document.documentElement.scrollTop,window.pageYOffset||0)
}
высота документа
function getDocumentTop() {
return document.documentElement.offsetHeight;
}
Код
дно
демонстрация нижней печати codepen
- Судя по прослушиванию событий прокрутки
可视区域,滚动高度,文档高度соотношение для достижения самой основной нагрузки на дно
<div id="app">
<ul>
<li v-for="item in list" :key="item" > {{item}}</li>
</ul>
</div>
created(){
// 初始化数据
this.list = Array.from(Array(10),(item,index)=>index)
// 通过监听滚动事件来判断 可视区域 , 滚动高度 ,文档高度的关系
window.addEventListener('scroll',()=>{
let isBottom = (getScrollHeight() + getWindowHeight()) >= getDocumentTop()
if(isBottom){
console.log('触底了',new Date())
let list = this.list
let last = list[list.length-1]
let newList = Array.from(Array(10),(item,index)=>index+last+1)
this.list.push(...newList)
}
})
}
Оптимизируйте и повторно используйте логику событий прокрутки
Извлеките логику прокрутки в миксины и поместите их в scroll.js. Функциональные точки оптимизации следующие:
- Увеличьте нижнее расстояние
- Регулирование событий прослушивателя событий прокрутки
- Добавьте нижнюю анимацию и объедините стили пользовательского интерфейса в scroll.js.
Моделирование событий запроса
Чтобы имитировать данные запроса, инкапсулируйте обещание и верните результат через одну секунду.
methods:{
// 返回一个 promise ,用于请求服务端数据
findDataList(){
let list = this.list
let last = list[list.length-1]
return new Promise((resolve)=>{
// 模拟服务端数据
let newList = Array.from(Array(10),(item,index)=>index+last+1)
setTimeout(() => {
resolve(newList)
}, 1000);
})
}
}
Слушатель событий прокрутки
Событие прокрутки запускается, чтобы определить, достигнуто ли текущее дно, и после достижения дна выполнить loadMore, чтобы инициировать запрос на получение данных с сервера.
created(){
let fn = throttle(()=>{
let isOver = (getScrollHeight() + getWindowHeight()) >= (getDocumentTop()- MIN_INSTANCE)
// 触底时进行数据加载
if(isOver){
// 创建加载组件
this.loadMore&&this.loadMore()
}
},DEALY_TIME)
window.addEventListener('scroll',fn)
},
Добавить анимацию дна
Поскольку мы извлекаем логику из миксинов, чтобы интегрировать нижнюю анимацию, мы используем Vue.extend() для реализации метода программной вставки стилей пользовательского интерфейса.
- Сначала определите стиль загружаемого компонента
<template>
<div id="loading-alert">
<i class="el-icon-loading"></i>
<span>{{ message }}</span>
</div>
</template>
<script>
export default {
props:{
message:{
type:String,
default:'正在加载更多数据'
}
},
};
- Вставьте загрузочный компонент, когда он опустится
import load from './load.vue'
data(){
return {
isLoading:false,
component:null
}
},
created(){
let fn = throttle(()=>{
let isOver = (getScrollHeight() + getWindowHeight()) >= (getDocumentTop()- MIN_INSTANCE)
// 触底时进行load组件显示
if(isOver){
// 判断loading组件是否已经存在,不存在就创建一个
if(!this.component){
this.component = extendComponents(load)
}
// 创建加载组件
this.loadMore&&this.loadMore()
// 判断当前状态来控制loading的组件显示与否
if(!this.isLoading){
this.component.$el.remove()
// 将loading组件置为空
this.component = null
}
}
},DEALY_TIME)
window.addEventListener('scroll',fn)
},
Подробный код
Полный код можноНажмите, чтобы просмотреть анимацию дна codepenо приведенном выше кодеextendComponentsДля реализации метода можно посмотреть подробный код, а можно просмотретьVue.extend программно вставляет компоненты
наконец
Логика и пользовательский интерфейс нижней части прокрутки интегрированы в scroll.js, а метод повторного использования может быть помещен в миксины и может быть разделен на v-директиву, чтобы мы могли принять, что связанный дом можно использовать не только для нижней части окна. событий также может быть实现单个元素的滚动事件触底的监听. Последующие версии могут быть реализованы в директиве v.