HTTP-запрос
Если вы изучали компьютерные сети, вы знаете, что мы просимn
картинкаhtml文件
на самом деле отправитn+1
запросы, т.к. парсинг в браузереhtml
встретились, когдаsrc
, запроситsrc
содержание позади.
Представьте, что если на нашей странице 1 000 000 изображений, то если задержка ожидания успешного ответа и загрузки этих изображений завершена, пользовательский опыт будет очень плохим.
Так можем ли мы сделать так, чтобы изображения загружались по запросу? Загружайте изображение, когда оно появляется в видимой области, вместо загрузки всего изображения в начале.
Ленивая загрузка изображения
шаблон:
<div @scroll="lazyLoad" ref="lazy">
<img v-for="(src, index) in imgs" src="##" :dataSrc="src" :key="index">
<!--more img-->
</div>
изменить источник изображения
Слушайте событие прокрутки самого внешнего div, перемещайтесь по изображению, чтобы определить положение изображения при запуске прокрутки, и отображайте его, если оно находится в видимой области.
loadImg() {
var img = this.$refs.lazy.getElementsByClassName("lazyImg");
// 已滚动高度+可视区高度
var top = this.$refs.lazy.scrollTop + this.$refs.lazy.clientHeight;
for(var i = 0; i < img.length; i++) {
if(img[i].offsetTop <= top) { // 在可视区内则显示图片
img[i].src = img[i].getAttribute("datasrc");
}
}
},
lazyLoad() {
this.loadImg();
}
Выше реализована ленивая загрузка изображений, эта статья здесь, до свидания.
Мостовой мешок с бобами внезапно обнаружил серьезную проблему: он будет продолжать срабатывать во время процесса прокатки.lazyLoad
Сделайте обход и оцените изображение, тогда вы будете делать бесчисленное количество циклов for. Что еще ужаснее, так это то, что изменение src один раз отправит запрос. При прокрутке наш цикл for будет оценивать и изменять изображение запроса src каждый раз с самого начала, тогда количество запросов можно себе представить.
Функция защиты от тряски
Если обход постоянно запускается во время процесса прокрутки и событие мониторинга для определения того, находится ли изображение в видимой области, потребляет много производительности, здесь используется функция защиты от сотрясения: когда пользователь прекращает прокрутку, положение изображения равномерно пройдена и определена
debounce(fn) {
// 函数防抖:用户停止操作之后触发
clearTimeout(this.timer);
this.timer = setTimeout(() => {
fn();
}, 1000);
}
Мы можем поместить метод загрузки изображения в debounce
lazyLoad() {
this.debounce(this.loadImg);
}
Таким образом, когда пользователь прокручивает страницу, отпускание руки будет выполняться толькоloadImg
Для обхода определить местоположение изображения.
Еще одна проблема: если пользователь прокручивает страницу снизу вверх и не отпускает, она не будет выполняться в течение этого периода.loadImg
, а это значит, что картинки на странице отображаться не будут, что сильно влияет на пользовательский опыт
Оптимизация защиты от сотрясений
Мы оговариваем, что если пользовательская высота подтягивания больше 500 пикселей, картинка в видимой области будет автоматически загружена один раз, здесь мы используем oldScrollTop для записи последней высоты подтягивания.
lazyLoad() {
// 如果上拉距离大于500px则自动加载
if(this.$refs.lazy.scrollTop - this.oldScrollTop > 500) {
this.loadImg();
this.oldScrollTop = this.$refs.lazy.scrollTop; // 更新oldScrollTop
} else { // 如果向下拉但小于500px则防抖加载
this.debounce(this.loadImg);
}
}
раскрывающаяся оптимизация
Когда пользователь тянет вниз, нам не нужно выполнятьlazyLoad
, потому что наше предыдущее изображение было загружено, поэтому мы можем изменить егоlazyLoad
lazyLoad() {
// 如果上拉距离大于500px则自动加载
if(this.$refs.lazy.scrollTop - this.oldScrollTop > 500) {
this.loadImg();
this.oldScrollTop = this.$refs.lazy.scrollTop;
} else if(this.$refs.lazy.scrollTop - this.oldScrollTop < 0) { // 如果向下拉则不做操作
return ;
} else { // 如果向下拉但小于500px则防抖加载
this.debounce(this.loadImg);
}
}
Уменьшите количество обходов
Самые важные оптимизации уже сделаны, но мы также можем оптимизировать некоторые мелкие детали.loadImg
В методе изображение каждый раз просматривается и проверяется с индекса 0, но после того, как пользователь подтянется, часть изображений уже загружена, поэтому нет необходимости проверять снова.
Мы можем использовать переменнуюlen
Запишите последнее изображение после его последней загрузки, а затем измените его.loadImg
loadImg() {
var img = this.getImages();
var top = this.$refs.lazy.scrollTop + window.screen.height;
// 从len开始检查
for(var i = this.len; i < img.length; i++) {
if(img[i].offsetTop <= top) {
img[i].src = img[i].getAttribute("datasrc");
this.len = i; // 更新len
}
}
}
Эпилог
Полная оптимизированная версия изображения загружается отложенно, и я инкапсулирую эту функцию в плагин vue.
Исходный код:vue-plugins
Библиотека плагинов будет постоянно обновляться, добро пожаловать на звездочку и форк~