Самый простой способ ленивой загрузки элементов DOM на странице.

Я представил, как динамически загружать изображение с помощью Angular, Динамическая загрузка изображения с помощью Angular. На этот раз я не буду использовать Angular или какой-либо другой фреймворк, а буду использовать только веб-стандарты, особенно пользовательские элементы и шаблоны.

Предположим, что на вашей странице более 100 изображений, и вы видите только два или три из них при загрузке страницы. Тогда почему браузеры загружают 100 изображений при инициализации страницы?

Невозможно не загрузить изображение, пока в вашем html есть теги ‹img›. Это означает, что вы должны изменить html, чтобы не было тегов изображения, и изменить html динамически, чтобы избежать начальной загрузки изображения. Однако динамическое изменение html — непростая задача, требующая большого количества сценариев.

На самом деле приведенное выше утверждение неверно. Когда ваш тег <img> находится в теге <template>, он не отображается. Я собираюсь использовать эту технику, и это шаги, которым я собираюсь следовать.

  1. Напишите HTML в <template>.
  2. Проверьте, находится ли элемент в окне просмотра.
  3. Визуализируйте шаблон, когда он находится в области просмотра.

1. Напишите HTML в <template>

<my-el> <-- This is the custom element -->
 <template>
   <div>This image is only rendered when this is in viewport.</div>
   <img src="https://picsum.photos/800/400/?image=10" />
 </template>
</my-el>
<my-el>
 <template>
   <div>This image is only rendered when this is in viewport.</div>
   <img src="https://picsum.photos/800/400/?image=20" />
 </template>
</my-el>
...

Без написания собственного пользовательского элемента, если вы запустите html-код, вы ничего не увидите, потому что template не отображается и изображение не будет загружено.

2. Проверьте, находится ли элемент в окне просмотра

Как указано в Документе IntersectionObserver MDN, мы можем определить, находится ли ваш элемент в области просмотра или нет.

Intersection Observer API предоставляет способ асинхронного наблюдения за изменениями в пересечении целевого элемента с элементом-предком или с областью просмотра документа верхнего уровня.

Это очень простой код для IntersectionObserver.

var observer = new IntersectionObserver(handler, options);
observer.observe(myEl);

handler : функция обратного вызова, которая будет запущена, когда наблюдаемый элемент находится в окне просмотра.

3. Визуализируйте шаблон, когда он находится в окне просмотра

Хотя вы можете многое сделать с помощью шаблона HTML5, в этой статье мы сосредоточимся только на template.content и document.importNode.

const templateEl = this.querySelector('template');
const clonedEl = document.importNode(templateEl.content, true);
myEl.appendChild(clonedEl);

Вышеупомянутое действие клонирует содержимое элемента шаблона и добавляет его в ваш элемент.

Вот и все. Вы получили все необходимые знания для динамической загрузки.

Для тех, кто хочет выполнять более настраиваемые действия, когда элемент находится в области просмотра или вне ее, вы можете запустить свое собственное событие. Как сказано в № 2, вы можете определить свой собственный обработчик, внутри которого вы можете запустить событие inview или outview следующим образом.

myIntersectionHandler(entries, observer) {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      this.activateTemplate(); #3 action
      this.dispatchEvent(new CustomEvent('inview'));
    } else {
      this.dispatchEvent(new CustomEvent('outview'));
    }
  });
}

Чтобы собрать все вместе, ниже приведен код пользовательского элемента my-inview. Фактически этот код является упрощенной версией Inview class of MCE.

class Inview extends HTMLElement {
  connectedCallback() {
    this.templateActivated = false;
    this.observer = new
      IntersectionObserver(this.handleIntersect.bind(this));
    this.observer.observe(this);
  }
  handleIntersect(entries, observer) {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        this.activateTemplate();
        this.dispatchEvent(new CustomEvent('inview'));
      } else {
        this.dispatchEvent(new CustomEvent('outview'));
      }
    });
  }
  activateTemplate() {
    if (this.templateActivated) return;
    const templateEl = this.querySelector('template');
    const clonedEl = document.importNode(templateEl.content, true);
    this.appendChild(clonedEl);
    this.templateActivated = true;
  }
}
customElements.define('my-inview', Inview);

Резюме

Удачного кодирования. :)

18 мая 2018 г.

Аллен Ким

Считаете ли вы это полезным? Если да, пожалуйста;
*
Хлопните кнопку 👏ниже️, чтобы другие тоже это увидели.
* Подпишитесь на Аллена в Твиттере( @allenhwkim)!