Прежде всего, для любых значков, таких как кнопки и c., Вы должны загружать и использовать шрифт с CSS, или для большей гибкости, просто SVG . Тем не менее, вы по-прежнему будете иметь различные фотографии и пользовательский контент, который вы хотели бы отобразить на своей странице.
Благодаря новым замечательным функциям современного Интернета, теперь мы можем лениво загружать этих присосок ! Мы будем использовать API-интерфейс Intersection Observer и Object.defineProperty для переопределения различных способов, которыми изображение может попасть в документ во время выполнения.
Вот код, который сделает это за вас. Вы можете просто скопировать его в файл Javascript и включить этот файл в свой документ. Или вы можете также проанализировать это, узнать и рассказать мне, что я пропустил:
(function () {
var Elp = Element.prototype;
var observer = new IntersectionObserver(function (entries, observer) {
entries.forEach(function (entry) {
if (!entry.target || entry.target.tagName.toUpperCase() !== 'IMG') {
return;
}
var img = entry.target;
var rect = entry.intersectionRect;
var src = img.getAttribute('data-defer-src');
if (src && rect.width > 0 && rect.height > 0) {
img.setAttribute('src', src);
img.removeAttribute('data-defer-src');
}
});
}, {
root: null, rootMargin: '0px', threshold: 0
});
// Observe whatever is on the page already
(function () {
var imgs = document.body.getElementsByTagName('img');
imgs = Array.from(imgs);
imgs.forEach(function (img) {
observer.observe(img);
});
})();
// Override innerHTML
var originalSet = Object.getOwnPropertyDescriptor(Elp, 'innerHTML').set;
var originalGet = Object.getOwnPropertyDescriptor(Elp, 'innerHTML').get;
Object.defineProperty(Elp, 'innerHTML', {
set: function (html) {
var element = document.createElement('div');
originalSet.call(element, html);
var imgs = element.getElementsByTagName('img');
var found = false;
imgs = Array.from(imgs);
imgs.forEach(function (img) {
var src = img.getAttribute('src');
if (src) {
img.setAttribute('data-defer-src', src);
img.removeAttribute('src');
found = true;
}
});
if (!found) {
originalSet.call(this, html);
return html;
}
originalSet.call(this, originalGet.call(element));
var imgs2 = this.getElementsByTagName('img');
imgs2 = Array.from(imgs);
imgs2.forEach(function (img) {
observer.observe(img);
});
},
get: originalGet
});
// Override any ways to insert elements
['insertBefore', 'appendChild'].forEach(function (fn) {
var orig = Elp[fn];
Elp[fn] = function (element) {
var imgs = null;
if (!element) {
return;
}
if (element.tagName && element.tagName.toUpperCase() === 'IMG') {
imgs = [element];
} else {
imgs = element.getElementsByTagName('img');
}
var found = false;
imgs.forEach(function (img) {
var src = img.getAttribute('src');
if (src) {
img.setAttribute('data-defer-src', src);
img.removeAttribute('src');
observer.observe(img);
found = true;
}
});
return orig.apply(this, arguments);
};
});
})();
Бонусные баллы, если вы можете настроить свой сервер для рендеринга <img data-defer-src="{{url here}}" alt="{{description here}}" title="{{title here}}">
вместо <img src="{{url here}}" alt="{{description here}}" title="{{title here}}">
. Потому что нет надежного способа во всех браузерах перехватывать изображения после их вставки в DOM с помощью