Что такое каркасный экран
Что такое каркасный экран? Skeleton Screen означает, что перед загрузкой данных страницы пользователю показывается общая структура страницы (серая карта-заполнитель), а фактическое содержимое страницы визуализируется после получения данных интерфейса и затем заменяется. Skeleton Screen — это элемент управления загрузкой, ставший популярным в последние два года, по сути, это эффект перехода в процессе загрузки интерфейса. Если общий контур веб-страницы можно отобразить заранее перед загрузкой, а затем постепенно подгружать реальный контент, это не только снизит беспокойство пользователя, но и сделает процесс загрузки интерфейса естественным и плавным, а также не заставлять веб-страницу оставаться пустой или мерцать в течение длительного времени. Это Скелет Экран!
Skeleton Screen может создать у людей ощущение, что содержимое страницы «отображено частично». По сравнению с традиционным эффектом загрузки, он может в определенной степени улучшить взаимодействие с пользователем.
Схема реализации каркасного экрана
В настоящее время существует примерно три технических решения для создания каркасных экранов:
- Используйте изображения, svg или вручную напишите код скелетного экрана: используя HTML + CSS, мы можем быстро реализовать эффект каркасного экрана, но перед лицом пересмотра визуального дизайна и изменений в требованиях наши последующие изменения скелетного экрана будут очень Пассивный, этот способ механизированной повторяющейся работы в настоящее время несколько лишен мобильности;
- Сгенерируйте соответствующий каркасный экран, предварительно отрендерив написанный вручную код: более зрелым решением является vue-skeleton-webpack-plugin, который использует vueSSR в сочетании с webpack для рендеринга написанных компонентов скелетного экрана vue во время построения и предварительно отрисовывает сгенерированный каркасные компоненты экрана.Узлы DOM и связанные стили вставляются в окончательный выходной html.
// webpack.conf.js
const SkeletonWebpackPlugin = require('vue-skeleton-webpack-plugin');
plugins: [
//...
new SkeletonWebpackPlugin({
webpackConfig: {
entry: {
app: resolve('./src/entry-skeleton.js')
}
}
})
]
Предпосылкой этой схемы также является написание компонентов каркасного экрана соответствующей страницы, а затем предварительный рендеринг узлов DOM, необходимых для создания каркасного экрана.Однако, поскольку эта схема напрямую связана с технологиями, связанными с vue, в сегодняшней среде там, где интерфейсный фреймворк разделен на три части, может потребоваться более гибкое и управляемое решение;
3. Внутренний инструмент Ele.me для создания каркасных страниц: это решение легко интегрируется с разработкой проекта с помощью подключаемого модуля webpack page-skeleton-webpack-plugin, который очень эффективен для автоматического создания каркасных экранов, и вы можете запустить интерфейс пользовательского интерфейса для настроить скелетный экран, но это будет неудовлетворительно перед лицом сложных страниц, а сгенерированные скелетные узлы экрана основаны на структуре и CSS самой страницы, и существует глубокая ситуация вложенности.Не слишком маленький, и только поддерживает режим истории.
// webpack.conf.js
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { SkeletonPlugin } = require('page-skeleton-webpack-plugin')
const path = require('path')
plugins: [
//...
new HtmlWebpackPlugin({
// Your HtmlWebpackPlugin config
}),
new SkeletonPlugin({
pathname: path.resolve(__dirname, `${customPath}`), // 用来存储 shell 文件的地址
staticDir: path.resolve(__dirname, './dist'), // 最好和 `output.path` 相同
routes: ['/', '/search'], // 将需要生成骨架屏的路由添加到数组中
})
]
Наша реализация
После тщательного размышления, разве этот экран-скелет не похож на страницу, состоящую из набора цветных блоков? По сравнению с существующим решением каркасного экрана, эта идея немного «укороченная». Если подумать, эти цветовые блоки генерируются на основе анализа узлов на текущей странице. Лучше анализировать узлы страницы с помощью JS и генерировать цветовые блоки для формирования каркасного экрана после операции DOM. Итак, вопрос в том, как точно анализировать узлы страницы и какие цветовые блоки должны генерироваться разными узлами?
Поскольку каркасный экран представляет собой общую структуру страницы, вам нужно использовать js для анализа структуры страницы в первую очередь. Перед анализом нам нужно разработать правило, чтобы определить, какие узлы нужно исключить? Какие типы узлов необходимы для создания цветных блоков? Как расположены сгенерированные цветовые блоки и так далее. Наши предварительные правила таковы:
- Просматривайте только те узлы DOM, которые видны в видимой области, в том числе: Нескрытые элементы, элементы с шириной и высотой больше 0, непрозрачные элементы, элементы, содержимое которых не является пробелом, элементы, расположенные в видимой области окна браузера и т. д.;
- Создание цветовых блоков для (фоновых) изображений, текста, элементов форм, аудио и видео, холста, блоков пользовательских функций и т. д.;
- Стиль, используемый узлами страницы, является неуправляемым, поэтому значение, связанное с размером стиля, неприемлемо.Вы можете получить абсолютное значение ширины, высоты и расстояния узла от области просмотра через getBoundingClientRect и рассчитать соответствующий процент к ширине и высоте текущего устройства в качестве блока цветов для адаптации к различному оборудованию;
Основываясь на этом наборе правил, мы начинаем генерировать каркас экрана: Во-первых, определите rootNode как входной узел, такой как document.body, и в то же время его удобно расширять для создания частичного скелетного экрана на странице, а запись рекурсивно проходится и фильтруется, чтобы изначально исключить невидимые узлы. .
function isHideStyle(node) {
return getStyle(node, 'display') === 'none' ||
getStyle(node, 'visibility') === 'hidden' ||
getStyle(node, 'opacity') == 0 ||
node.hidden;
}
Затем определите характеристики элемента, чтобы определить, выполняются ли условия генерации.Для областей, которые соответствуют условиям, "равная обработка" будет генерировать цветовые блоки для соответствующих областей. «Равное обращение» означает, что для квалифицированной области не различаются определенные элементы, не учитывается уровень структуры и не учитывается стиль, а также равномерно генерируется цветовой блок div в соответствии с абсолютным значением расстояния между областью. и окно просмотра. Причина этого в том, что сгенерированные узлы являются плоскими и относительно небольшими, при этом избегая дополнительного чтения таблиц стилей и поддерживая внешний вид экрана-скелета за счет извлечения стилей.Этот унифицированный метод генерации делает узлы экрана-скелета более управляемыми. Основываясь на приведенной выше идее «сокращения», скелетный экран, сгенерированный этим методом, состоит из блоков чистого цвета DOM.
Методы для генерации цветовых блоков:
const blocks = [];
// width,height,top,left都是算好的百分比
function drawBlock({width, height, top, left, zIndex = 9999999, background, radius} = {}) {
const styles = [
'position: fixed',
'z-index: '+ zIndex,
'top: '+ top +'%',
'left: '+ left +'%',
'width: '+ width +'%',
'height: '+ height +'%',
'background: '+ background
];
radius && radius != '0px' && styles.push('border-radius: ' + radius);
// animation && styles.push('animation: ' + animation);
blocks.push(`<div style="${ styles.join(';') }"></div>`);
}
Рисовать цветные блоки несложно, а анализ и подтверждение перед рисованием — настоящая суть и сложность этой схемы. Например, для страницы со сложной структурой страницы или большим количеством больших изображений область, склеенная изображениями, не имеет границ, и сгенерированные цветовые блоки будут находиться рядом друг с другом, что приведет к неудовлетворительным местам. Другой пример: в области блока карточек, которая содержит много маленьких блоков, отвечающих условиям генерации, генерируется ли цветовой блок на основе блока карточек или маленьких блоков внутри? Если преобладает мелкий блок, результат рисования может вообще не ощущаться как карточный блок, а возможностей для методов и стилей компоновки слишком много, что сильно увеличивает неопределенность. А если цветовой блок генерируется на основе блока карт, то для блока карт должны быть созданы специальные правила.
В настоящее время, поскольку структура страницы не является особенно сложной, не изобилует изображениями, не особенно «элегантной» компоновкой, этот метод уже может создать идеальный экран-скелет. А для тех случаев, которые далеки от ожиданий, мы предоставляем две функции-хука для тонкой настройки:
- Функция init, которая выполняется перед началом обхода узлов, подходит для таких операций, как удаление мешающих узлов.
- Функция includeElement(node, draw) может вызывать метод рисования для пользовательского рисования при переходе к указанному узлу.
С помощью описанных выше шагов код каркаса экрана может быть сгенерирован непосредственно в браузере.
запустить в браузере
Поскольку отправной точкой нашего решения является обход узлов на странице с помощью простых операций DOM, создание цветовых блоков в соответствующей области в соответствии с установленными правилами и, наконец, формирование скелетного экрана страницы, поэтому основной код может выполняться напрямую. на стороне браузера;
const createSkeletonHTML = require('draw-page-structure/evalDOM')
createSkeletonHTML({
// ...
background: 'red',
animation: 'opacity 1s linear infinite;'
}).then(skeletonHTML => {
console.log(skeletonHTML)
}).catch(e => {
console.error(e)
})
Автоматически генерировать каркасные экраны с помощью Puppeteer
Хотя этот метод уже может генерировать код каркасного экрана, он все еще недостаточно автоматизирован, чтобы автоматически загружать сгенерированный код каркасного экрана на указанную страницу. Итак, мы разработали сопутствующий инструмент CLI. Этот инструмент запускает страницу через Puppeteer и внедряет скрипт evalDOM.js на страницу для автоматического выполнения.В результате выполнения сгенерированный скелетный код экрана вставляется на страницу приложения.
Наш план примерно такой:
Далее давайте посмотрим, как использовать инструмент командной строки для создания каркасного экрана.Это займет максимум четыре шага:
- Установить глобально, npm i draw-page-structure –g
- Инициализация DPS Создать профиль DPS.CONFIG.JS
- Измените dps.config.js для соответствующей конфигурации.
- dps start начинает генерировать экран скелета
Всего несколько простых шагов, но без громоздкой настройки:
Вообще говоря, вам нужно настроить dps.config.js в соответствии с вашим собственным проектом.Обычные элементы конфигурации:
- url: Адрес страницы скелетного экрана, который будет сгенерирован.
- output.filepath: файл, записанный сгенерированным скелетным узлом экрана.
- output.injectSelector: Позиция, в которую вставляется узел каркаса экрана, по умолчанию #app
- background: Цвет темы экрана скелета
- animation: свойства анимации css3
- rootNode: True для создания каркасного экрана для модуля.
- device: тип устройства, мобильный по умолчанию
- extraHTTPHeaders: добавить заголовок запроса
- init: операция перед началом генерации
- includeElement(node, draw): Настройте, как генерируется узел
- writePageStructure(html, filepath): Узел скелетного экрана обратного вызова
Пожалуйста, перейдите к использованию подробных кодов и инструментовGithub;
Достигнуты предварительные результаты:
- Официальная домашняя страница членов JD PLUS:
- На домашней странице официального члена JD PLUS эффект скелетного экрана, созданный этим решением:
- Конец Baidu Mobile Home:
- На домашней странице мобильного терминала Baidu эффект каркасного экрана, созданный этим решением:
Суммировать
Выше приведена схема автоматической генерации каркасного экрана на основе DOM, ядром которой является функция evalDOM. Производительность этой схемы удовлетворительна во многих сценариях. Тем не менее, существует слишком много возможностей для компоновки веб-страниц и комбинаций стилей, и до достижения идеальных результатов в различных сценариях еще далеко, но, поскольку вы уже в пути, давайте смело двигаться вперед!
Добро пожаловать в звезду, добро пожаловать в PR!Github