предисловие
Некоторое время назад я изучал реализацию внешней платформы мониторинга/встраивания аномалий.
Размышляя о решении, я подумал о собственном наблюдателе браузера и API жизненного цикла страницы.
Поэтому, просматривая данные, я случайно обнаружил, что современные браузеры поддерживают до четырех разных типов наблюдателей:
-
Intersection Observer, перекрестный наблюдатель. -
Mutation Observer, наблюдатель изменений. -
Resize Observer, наблюдатель представления. -
Performance Observer, наблюдатель за производительностью
| IntersectionObserver | MutationObserver | ResizeObserver | PerformanceObserver | |
|---|---|---|---|---|
| использовать | Посмотрите, виден ли элемент в окне просмотра | Наблюдайте за изменениями в DOM | Наблюдайте за изменением размера области просмотра | Мероприятие по отслеживанию показателей производительности |
| метод | observe() disconnect() takeRecords() |
observe() disconnect() takeRecords() unobserve() |
observe() disconnect() unobserve() |
observe() disconnect() takeRecords() |
| заменять | Dom Mutation events | getBoundingClientRect() возвращает размер элемента и его положение относительно видимого окна. События прокрутки и изменения размера |
Изменить размер события | Интерфейс производительности |
| использовать | 1. Бесконечная прокрутка 2. Ленивая загрузка изображения 3. Точка захоронения интереса 4. Управление анимацией/видео исполнением (оптимизация производительности) |
1. Более высокая производительность привязки данных и ответа 2. Реализуйте параллаксную прокрутку 3. Предварительная загрузка изображения 4. Реализуйте форматированный текстовый редактор |
1. Более умные адаптивные макеты (заменяет @media) 2. Адаптивные компоненты |
1. Мониторинг производительности более мелких частиц 2. Проанализируйте влияние производительности на бизнес (влияет ли быстрое/медленное взаимодействие на продажи) |
## 1. IntersectionObserver: перекрестный наблюдатель |
IntersectionObserverИнтерфейс, который обеспечивает способ асинхронного наблюдения за целевым элементом и его предками или окном просмотра документа верхнего уровня (viewport) метод, который пересекает состояние, элемент-предок и область просмотра (viewport)называется корнем (root)
1. Значение внешности
Хотите рассчитать положение элементов веб-страницы, очень зависящее отDOMЯвный запрос статуса. Но эти запросы являются синхронными, влекут за собой дорогостоящие накладные расходы на вычисления (перерисовка и перекомпоновка), а постоянный опрос приводит к значительной потере производительности.
Поэтому были разработаны следующие решения:
- Создайте пользовательскую предварительную загрузку и ленивую загрузку DOM и данных.
- Реализует привязанный к данным высокопроизводительный список прокрутки, который загружает и отображает подмножество набора данных.
- пройти через
scrollи другие события или в виде плагинов для расчета реальной видимости элемента.
И все они имеют несколько общих черт:
- Базовая форма реализации — это «пассивный запрос», который запрашивает каждый элемент относительно некоторых элементов (глобальное окно просмотра).
- Информация может передаваться асинхронно (например, из другого потока), и единообразной обработки перехвата ошибок не существует.
-
webПоддержка платформ отсутствует, и у каждой свой процессинг. Для совместимости требуется, чтобы разработчики потребляли много энергии.
2. IntersectionObserverПреимущества
Intersection Observer APIПредоставив разработчикам новый метод асинхронного запроса элемента относительно других элементов или глобального окна просмотра, чтобы решить вышеуказанные проблемы:
-
Асинхронная обработкаустраняет дорогие
DOMи стилевые запросы, непрерывный опрос и необходимость использования пользовательских плагинов. - Благодаря устранению необходимости в этих методах приложения могут работать значительно медленнее.
CPU,GPUи затрат на ресурсы.
3. IntersectionObserverосновное использование
использоватьIntersectionObserver APIТребуются три основных шага:
- Создать наблюдателя
- Определить события обратного вызова
- Определите целевой объект для наблюдения
1.Создать наблюдателя
const options = {
root: document.querySelector('.scrollContainer'),
rootMargin: '0px',
threshold: [0.3, 0.5, 0.8, 1] }
const observer = new IntersectionObserver(handler, options)
Эти параметры объясняются на местном языке как:
-
root: указывает корневой элемент -
rootMargin: задает корневое поле (наблюдаемый диапазон влияния корневого элемента) с использованием синтаксиса, аналогичного настройке полей CSS. -
threshold: порог, может быть массивом.[0.3]Означает, что обработчик вызывается, когда целевой элемент видим на 30% внутри элемента, указанного корневым элементом.
2. Определить события обратного вызова
Функция обратного вызова запускается, когда целевой элемент и корневой элемент пересекают пороговое значение.
function handler (entries, observer) {
entries.forEach(entry => {
// 每个成员都是一个IntersectionObserverEntry对象。
// 举例来说,如果同时有两个被观察的对象的可见性发生变化,entries数组就会有两个成员。
// entry.boundingClientRect
// entry.intersectionRatio
// entry.intersectionRect
// entry.isIntersecting
// entry.rootBounds
// entry.target
// entry.time
});
}
- отметка времени
- rootОграничивает положение корневого элемента
- Информация о положении целевого элемента boundingClientRect
- пересечениеRect Информация о местоположении перекрестка
- IntersectionRatio Видимое соотношение целевого элемента, см. рисунок ниже.
- цель.
3. Определите целевой объект для наблюдения
Доступ к любому целевому элементу можно получить, вызвав.observer(target)метод наблюдения.
const target = document.querySelector(“.targetBox”);
observer.observe(target);
Кроме того, есть два метода:
перестать слушать цель
observer.unobserve(target)
Прекратить прослушивание всех целей
observer.disconnect()
4. Пример 1: Ленивая загрузка изображений
HTML:
<img src="placeholder.png" data-src="img-1.jpg">
<img src="placeholder.png" data-src="img-2.jpg">
<img src="placeholder.png" data-src="img-3.jpg">
<!-- more images -->
сценарий:
let observer = new IntersectionObserver(
(entries, observer) => {
entries.forEach(entry => {
/* 替换属性 */
entry.target.src = entry.target.dataset.src;
observer.unobserve(entry.target);
});
},
{rootMargin: "0px 0px -200px 0px"});
document.querySelectorAll('img').forEach(img => { observer.observe(img) });
Приведенный выше пример означает, что изображение будет загружено только тогда, когда оно достигнет области просмотра и будет на 200 пикселей ниже.
5. Пример 2: Точки захоронения интересов
Что касается скрытых процентов, более общее решение:
const boxList = [...document.querySelectorAll('.box')]
var io = new IntersectionObserver((entries) =>{
entries.forEach(item => {
// intersectionRatio === 1说明该元素完全暴露出来,符合业务需求
if (item.intersectionRatio === 1) {
// 。。。 埋点曝光代码
io.unobserve(item.target)
}
})
}, {
root: null,
threshold: 1, // 阀值设为1,当只有比例达到1时才触发回调函数
})
// observe遍历监听所有box节点
boxList.forEach(box => io.observe(box))
Что касается того, как судить, заинтересован ли пользователь, метод записи зависит от мнения:
- Он находится посередине экрана и держится более 2 секунд, а засчитывается один раз.
- Наведите указатель мыши на область, чтобы запустить таймер для записи времени.
-
PCКоличество щелчков мышью/время наведения записывается на терминале, а мобильный терминал записываетtouchмероприятие
Я не начну писать здесь (я ленивый).
6. Управление анимацией/видео исполнением
Вот версия контрольного видео
HTML:
<video src="OSRO-animation.mp4" controls=""></video>
js:
let video = document.querySelector('video');
let isPaused = false; /* Flag for auto-paused video */
let observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if(entry.intersectionRatio!=1 && !video.paused){
video.pause(); isPaused = true;
}
else if(isPaused) {video.play(); isPaused=false}
});
}, {threshold: 1});
observer.observe(video);
Эффект:
2. Mutation Observer: сменить наблюдателя
интерфейс обеспечивает пары мониторинга
DOMСпособность вносить изменения. Он предназначен для старогоMutationEventsЗамена функции, котораяDOM3 Eventsчасть спецификации.
1. Значение внешности
Ведь да
MutationEventsФункционал более чем удовлетворительный:
- существует
MDNТак же написано вDOM EventПризнанные недостатки в API, против использования. - Основные недостатки: проблемы с производительностью и кросс-браузерная поддержка.
- для
DOMДобавить кmutationСлушатель крайне понижен и дополнительно модифицированDOMПроизводительность документа (в 1,5-7 раз медленнее), кроме того, удаление прослушивателя не устраняет ущерб.
From: "Мониторинг завершения загрузки и изменений DOM - приложение MutationObserver"
MutationEventsПринцип: прослушивание путем связывания событийDOM
На первый взгляд все кажется нормальным, поэтому давайте перечислим связанные отслеживаемые события:
DOMAttributeNameChanged
DOMCharacterDataModified
DOMElementNameChanged
DOMNodeInserted
DOMNodeInsertedIntoDocument
DOMNodeRemoved
DOMNodeRemovedFromDocument
DOMSubtreeModified
Не помните, при таком количестве событий браузеры разных ядер и версий боятся, что совместимость будет вне времени.
2. MutationObserverПреимущества
а такжеMutation ObserverПреимущества:
-
MutationEventsСобытия запускаются синхронно, т.DOMИзменение немедленно вызовет соответствующее событие; -
Mutation Observerзапускается асинхронно,DOMизменения не будут запущены немедленно, а будут ждать, пока все текущиеDOMСрабатывает, когда операция завершена. - Вы можете контролировать цель через элементы конфигурации
DOMЖурнал изменений следующего дочернего элемента
Проще говоря:异步万岁!
3. MutationObserverосновное использование
использоватьMutationObserver APIТребуются три основных шага:
- Создать наблюдателя
- Определите функцию обратного вызова
- Определите целевой объект для наблюдения
1. Создайте наблюдателя
let observer = new MutationObserver(callback);
2. Определите функцию обратного вызова
Функция обратного вызова в приведенном выше коде будет вызываться после каждого изменения DOM. Функция обратного вызова принимает два параметра, первый — это массив изменений, а второй — экземпляр наблюдателя, вот пример:
function callback (mutations, observer) {
mutations.forEach(function(mutation) {
console.log(mutation);
});
});
каждый из нихmutationИметь соответствующийMutationRecordобъект, записанныйDOMЖурнал изменений для каждого изменения
MutationRecordОбъект содержит информацию о DOM и имеет следующие свойства:
| Атрибуты | значимость |
|---|---|
type |
тип наблюдаемого движения (attribute,characterDataилиchildList) |
target |
измененныйDOMузел |
addedNodes |
добавленDOMузел |
removedNodes |
удаленDOMузел |
previousSibling |
предыдущий одноуровневый узел или возврат, если нетnull
|
nextSibling |
следующий родственный узел или возврат, если нетnull
|
attributeName |
Свойства, которые изменились. если установленоattributeFilter, возвращаются только предварительно указанные свойства |
oldValue |
Значение до изменения. Это свойство толькоattributeа такжеcharacterDataИзменения действительны, если они происходятchildListменять, возвращатьnull
|
3. Определите целевой объект для наблюдения
MutationObserver.observe(dom, options)
Запустите прослушиватель и получите два параметра.
- Первый параметр: наблюдаемый
DOMузел. - Второй параметр: настроить изменения, которые необходимо соблюдать
options.
mutationObserver.observe(content, {
attributes: true, // Boolean - 观察目标属性的改变
characterData: true, // Boolean - 观察目标数据的改变(改变前的数据/值)
childList: true, // Boolean - 观察目标子节点的变化,比如添加或者删除目标子节点,不包括修改子节点以及子节点后代的变化
subtree: true, // Boolean - 目标以及目标的后代改变都会观察
attributeOldValue: true, // Boolean - 表示需要记录改变前的目标属性值
characterDataOldValue: true, // Boolean - 设置了characterDataOldValue可以省略characterData设置
// attributeFilter: ['src', 'class'] // Array - 观察指定属性
});
приоритет :
-
attributeFilter/attributeOldValue>attributes -
characterDataOldValue>characterData -
attributes/characterData/childList(или более конкретный) хотя бы один из них верен; - Определенный элемент существует, соответствующий параметр можно игнорировать или его необходимо
true
Кроме того, есть два метода:
Перестань смотреть. После звонка обозреватель больше не будет срабатывать, а подписка будет отписана
MutationObserver.disconnect()
Очистить историю изменений. То есть необработанные изменения больше не обрабатываются. Этот метод возвращает массив измененных записей.Обратите внимание, что этот метод вступает в силу немедленно.
MutationObserver.takeRecords()
4. Пример 1:MutationObserverСлушайте изменения текста
Основное использование:
const target = document.getElementById('target-id')
const observer = new MutationObserver(records => {
// 输入变更记录
})
// 开始观察
observer.observe(target, {
characterData: true
})
Здесь может быть несколько процедур.
- Пузырьковое пасхальное яйцо для чата обнаруживает в тексте указанный пакет строки/смайлика и запускает анимацию падения эмодзи, аналогичную чату WeChat.
- Поиск горячей темы в поле ввода, при вводе "
#», активируйте поле поиска, чтобы предварительно просмотреть текст или выделить темы.
имеетVueНебольшой плагин реализован так:
5. Пример 2: Сценарий мини-игры Color Block
Эта реализация тоже очень хороша:
Логика игры очень проста: когда цвет цветного блока в середине меняется, в течение отведенного времени выберите вариант того же цвета, что и вариант внизу, чтобы набрать очки. Сложность в том, что чем дальше уровень, тем больше вариантов, и ближе цвет вариантов, например:
На самом деле принцип очень прост, то есть соблюдайте цветовые блоки.backgroundColor(изменение атрибутаattributes), затем вызовите событие clicke.click().
var targetNode = document.querySelector('#kolor-kolor');
var config = { attributes: true };
var callback = function(mutationsList, observer) {
if (mutationsList[0].type == 'attributes') {
console.log('attribute change!');
let ans = document.querySelector('#kolor-kolor').style.backgroundColor;
document.querySelectorAll('#kolor-options a').forEach( (e) => {
if (e.style.backgroundColor == ans) {
e.text = 'Ans!';
e.click()
}
})
}
};
var observer = new MutationObserver(callback);
observer.observe(targetNode, config);
3. ResizeObserver, наблюдатель представления
ResizeObserver APIэто новыйJavaScript API,а такжеIntersectionObserver APIОчень похожи, они оба позволяют нам прослушивать изменения элемента.
1. Значение внешности
- Процесс разработки проблема часто встречалась, заключается в том, как контролировать
divменяется размер. - Но, как известно, для контроля
divизменений размера, прикрепите слушателей кwindowсерединаresizeмероприятие. - Но это может легко привести к проблемам с производительностью из-за большого количества триггерных событий.
- Другими словами, используйте
window.resizeОбычно расточительно, потому что сообщает нам, как изменяется размер каждого окна просмотра, а не только когда изменяется размер элемента.
- а также
resizeСобытие срабатывает почти 60 раз в секунду, легко вызывая проблемы с производительностью при изменении размера окна.
Например, если вы хотите изменить размер элемента, вам нужноresizeфункция обратного вызоваcallback()вызыватьgetBoundingClientRectилиgetComputerStyle. Но если вы не будете тщательно обрабатывать все операции чтения и записи, вы получите беспорядочный макет. Например, этот небольшой пример:
2. ResizeObserverПреимущества
ResizeObserver APIЕсть два основных преимущества:
- мелкозернистый
DOMнаблюдение за элементом вместоwindow - Никаких дополнительных затрат на производительность, инициирует вызов до или после макета чертежа.
3. ResizeObserverосновное использование
использоватьResizeObserver APIТакже есть три шага:
- Создать наблюдателя
- Определите функцию обратного вызова
- Определите целевой объект для наблюдения
1. Создайте наблюдателя
let observer = new ResizeObserver(callback);
2. Определите функцию обратного вызова
const callback = entries => {
entries.forEach(entry => {
})
}
Каждыйentryэто объект с двумя свойствамиcontentRectа такжеtarget
contentRectВсе это некоторая информация о местоположении:
| Атрибуты | эффект |
|---|---|
bottom |
top + heightзначение |
height |
Высота самого элемента, исключаяpadding,borderстоимость |
left |
padding-leftзначение |
right |
left + widthзначение |
top |
padidng-topзначение |
width |
Ширина самого элемента, исключаяpadding,borderстоимость |
x |
размер сtopтакой же |
y |
размер сleftтакой же |
3. Определите целевой объект для наблюдения
observer.observe(document.body)
unobserveМетод: отменить наблюдение за одним узлом
observer.unobserve(document.body)
disconnectМетод: отменить все наблюдения узлов
observer.disconnect(document.body)
4. Пример 1: Масштабированный градиентный фон
html:
<div class="box">
<h3 class="info"></h3>
</div>
<div class="box small">
<h3 class="info"></h3>
</div>
Добавить стиль точки:
body {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
padding: 2vw;
box-sizing: border-box;
}
.box {
text-align: center;
height: 20vh;
border-radius: 8px;
box-shadow: 0 0 4px rgba(0,0,0,.25);
display: flex;
justify-content: center;
align-items: center;
padding: 1vw
}
.box h3 {
color: #fff;
margin: 0;
font-size: 5vmin;
text-shadow: 0 0 10px rgba(0,0,0,0.4);
}
.box.small {
max-width: 550px;
margin: 1rem auto;
}
JavaScriptКод:
const boxes = document.querySelectorAll('.box');
let callbackFired = 0;
const myObserver = new ResizeObserver(entries => {
for (let entry of entries) {
callbackFired++
const infoEl = entry.target.querySelector('.info');
const width = Math.floor(entry.contentRect.width);
const height = Math.floor(entry.contentRect.height);
const angle = Math.floor(width / 360 * 100);
const gradient = `linear-gradient(${ angle }deg, rgba(0,143,104,1) 50%, rgba(250,224,66,1) 50%)`;
entry.target.style.background = gradient;
infoEl.innerText = `
I'm ${ width }px and ${ height }px tall
Callback fired: ${callbackFired}
`;
}
});
boxes.forEach(box => {
myObserver.observe(box);
});
Вот что вы видите, когда перетаскиваете окно браузера, чтобы изменить его размер:
5. Пример 2: реактивныйVueкомпоненты
- Предположим, вы хотите создать компонент postItem на большом экране с эффектом отображения.
- Нужен этот эффект на мобильном телефоне:
просто@mediaМожно добиться:
@media only screen and (max-width: 576px) {
.post__item {
flex-direction: column;
}
.post__image {
flex: 0 auto;
height: auto;
}
}
- Но легко увидеть следующий макет, когда вы просматриваете страницу на большем, чем ожидалось, экране (слишком большом):
@mediaСамая большая проблема с запросом:
- Отклик компонента зависит от размера экрана, а не от его собственного размера.
Вот реализация версии команды:
использовать:
Эффект:
Этоvue-responsive-componentsКонкретный код реализации библиотеки, а также реализацию в виде компонентов можно посмотреть, если интересно.
4. PerformanceObserver: наблюдатель за производительностью
Это браузер иNode.jsAPI, которые существуют в обоихW3CизPerformance TimelineТехнические характеристики
- В браузере мы можем использовать объект окна, чтобы получить
window.performanceа такжеwindow.PerformanceObserver. - пока в
Node.jsтребуется в программеperf_hooksЧтобы получить объект производительности, выполните следующие действия:const { PerformanceObserver, performance } = require('perf_hooks');
1. Значение внешности
Первый взглядPerformanceинтерфейс:
-
Вы можете получить информацию о производительности на текущей странице. это
High Resolution Time APIчастьPerformance Timeline API,Navigation Timing AP,User Timing APIа такжеResource Timing API. -
Performance APIЭто знакомый интерфейс, который записывает огромную коллекцию объектов с несколькими показателями производительности.
- Чтобы получить запись производительности загрузки страницы, вам нужно вызвать
performance.getEntriesилиperformance.getEntriesByNameчтобы получить. - И эффективность исполнения может быть достигнута только
performance.nowвычислять.
Для решения вышеуказанной проблемы вPerformance Timeline Level 2, за исключением того, что расширенныйPerformanceВ дополнение к основному определениюPerformanceObserverинтерфейс.
2. PerformanceObserverПреимущества
PerformanceObserverявляется внутреннимPerformanceРеализован шаблон наблюдателя, который также немного поддерживается современными браузерами.Observerодин.
Откуда: Знаете ли вы уровень 2 временной шкалы производительности? 》
Он решает следующие 3 проблемы:
- Избегайте незнания того, когда произойдут события производительности, требующие повторных ротаций
timelineПолучить записи. - Избегайте дублирования логики для получения разных индикаторов данных о производительности.
- Избегайте расовых отношений, когда другим ресурсам необходимо управлять буфером производительности браузера.
W3CОфициальный документ веб-сайта призывает разработчиков использовать как можно большеPerformanceObserver, вместо прохожденияPerformanceПолучите параметры и показатели производительности.
3. PerformanceObserverиспользование
использоватьPerformanceObserver APIТребуются три основных шага:
- Создать наблюдателя
- Определите событие функции обратного вызова
- Определите целевой объект для наблюдения
1. Создайте наблюдателя
let observer = new PerformanceObserver(callback);
2. Определите событие функции обратного вызова
const callback = (list, observer) => {
const entries = list.getEntries();
entries.forEach((entry) => {
console.log(“Name: “ + entry.name + “, Type: “ + entry.entryType + “, Start: “ + entry.startTime + “, Duration: “ + entry.duration + “\n”); });
}
каждый из нихlistявляется полнымPerformanceObserverEntryListОбъект:Содержит три метода
getEntries,getEntriesByType,getEntriesByName:
| метод | эффект |
|---|---|
| getEntries() | Возвращает список, содержащий некоторые объекты, используемые для переноса различных данных о производительности, без какой-либо фильтрации. |
| getEntriesByType() | Возвращает список, содержащий некоторые объекты, используемые для переноса различных данных о производительности, отфильтрованных по типу. |
| getEntriesByName() | Возвращает список, содержащий некоторые объекты для хранения различных данных о производительности, отфильтрованных по имени. |
3. Определите целевой объект для наблюдения
observer.observe({entryTypes: ["entryTypes"]});
observer.observe(...)Метод принимает допустимый тип записи, который можно наблюдать. Эти типы входных данных могут принадлежать различным API производительности, таким какUser tmingилиNavigation Timing API. ЭффективныйentryTypeстоимость:
| Атрибуты | псевдоним | Типы | описывать |
|---|---|---|---|
| рамка, навигация | PerformanceFrameTiming, PerformanceNavigationTiming | URL | Адрес файла. |
| resource | PerformanceResourceTiming | URL | Разрешенный URL запрошенного ресурса. |
| mark | PerformanceMark | DOMString | Имя, используемое при создании отметки путем вызова performance.mark(). |
| measure | PerformanceMeasure | DOMString | Имя, используемое при создании показателя путем вызова performance.measure(). |
| paint | PerformancePaintTiming | DOMString | Либо «первая краска», либо «первая содержательная краска». |
| longtask | PerformanceLongTaskTiming | DOMString | Случаи сообщения о длительных задачах |
4. Пример 1: Мониторинг статических ресурсов
function filterTime(a, b) {
return (a > 0 && b > 0 && (a - b) >= 0) ? (a - b) : undefined;
}
let resolvePerformanceTiming = (timing) => {
let o = {
initiatorType: timing.initiatorType,
name: timing.name,
duration: parseInt(timing.duration),
redirect: filterTime(timing.redirectEnd, timing.redirectStart), // 重定向
dns: filterTime(timing.domainLookupEnd, timing.domainLookupStart), // DNS解析
connect: filterTime(timing.connectEnd, timing.connectStart), // TCP建连
network: filterTime(timing.connectEnd, timing.startTime), // 网络总耗时
send: filterTime(timing.responseStart, timing.requestStart), // 发送开始到接受第一个返回
receive: filterTime(timing.responseEnd, timing.responseStart), // 接收总时间
request: filterTime(timing.responseEnd, timing.requestStart), // 总时间
ttfb: filterTime(timing.responseStart, timing.requestStart), // 首字节时间
};
return o;
};
let resolveEntries = (entries) => entries.map(item => resolvePerformanceTiming(item));
let resources = {
init: (cb) => {
let performance = window.performance || window.mozPerformance || window.msPerformance || window.webkitPerformance;
if (!performance || !performance.getEntries) {
return void 0;
}
if (window.PerformanceObserver) {
let observer = new window.PerformanceObserver((list) => {
try {
let entries = list.getEntries();
cb(resolveEntries(entries));
} catch (e) {
console.error(e);
}
});
observer.observe({
entryTypes: ['resource']
})
} else {
window.addEventListener('load', () => {
let entries = performance.getEntriesByType('resource');
cb(resolveEntries(entries));
});
}
},
};
Справочные статьи и резюме
Есть много справочных статей:
- Мониторинг ресурсов
- Media Queries Based on Element Width with MutationObserver
- Используйте индикатор производительности
- A Few Functional Uses for Intersection Observer to Know When an Element is in View
- Getting To Know The MutationObserver API
- Different Types Of Observers Supported By Modern Browsers
- THE RESIZE OBSERVER EXPLAINED
- A Look at the Resize Observer JavaScript API
Эти четыре наблюдателя очень подходят для интеграции в системы мониторинга.
и иметь соответствующиеPolyfillsреализация версии.
Сводки и документы в интернете разной глубины.Если есть ошибки прошу поправить.