Нижние миксины прокрутки Vue

Vue.js

предисловие

Мы часто видим анимацию, похожую на загрузку данных на стороне приложения.Далее давайте реализуем анимацию загрузки с прокруткой снизу и как повторно использовать эту логику.

Как определить, что прокрутка достигла дна

Взгляните на некоторые фотографии:

Дело 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. Функциональные точки оптимизации следующие:

  1. Увеличьте нижнее расстояние
  2. Регулирование событий прослушивателя событий прокрутки
  3. Добавьте нижнюю анимацию и объедините стили пользовательского интерфейса в 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() для реализации метода программной вставки стилей пользовательского интерфейса.

  1. Сначала определите стиль загружаемого компонента
<template>
    <div id="loading-alert">
      <i class="el-icon-loading"></i>
      <span>{{ message }}</span>
    </div>
</template>

<script>
export default {
  props:{
    message:{
      type:String,
      default:'正在加载更多数据'
    }
  },
};
  1. Вставьте загрузочный компонент, когда он опустится
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.