Использование скелетного экрана
- Используется как загрузка для коммутации маршрутизации в спа, совмещенная с жизненным циклом компонента и временем возврата ajax запроса (используется как загрузка). Как фронтенд-разработчик, который наиболее тесно связан с пользователями, пользовательский опыт заслуживает самого пристального внимания. Что касается отображения состояния загрузки страницы, основное направление в основном включает график загрузки и индикатор выполнения. Кроме того, все больше и больше приложений используют метод «скелетного экрана» для отображения незагруженного контента, предоставляя пользователям совершенно новый опыт.
- В качестве оптимизации для рендеринга в верхней части страницы
Скелетный экран архитектуры Vue
Наброски идей
- Определите абстрактный компонент и получите слот в функции рендеринга абстрактного компонента.
- Глубоко перебирать слоты, добавляя каждый элемент к имени класса gm-skeleton.
- Предварительно опустошите vnode textContent, чтобы гарантировать, что текст по умолчанию не будет отображаться при появлении скелетного экрана.
- вернуться к игровым автоматам
определить абстрактный компонент
Что такое абстрактный компонент Компонент, который пропускается во время рендеринга и выполняет только операции во время выполнения
export default {
name: 'GmSkeleton',
abstract: true // 抽象组件的属性
}
Получение слотов и каркас экрана инициализации
render(h) {
const slots = this.$slots.default || [h('')]
this.$nextTick().then(() => {
this.handlerPrefix(slots, this.showSpin ? this.addSkeletPrefix : this.removeSkeletPrefix)
})
return slots.length > 1 ? h('div', {
staticClass: this.showSpin ? 'g-spinner' : ''
}, slots) : slots
}
Здесь мы размещаем метод обработки слотов в nextTick,Потому что handlerPrefix должен получить настоящий DOM, nextTick используется для выполненияпосле сортировкиВсе методы в очереди обновления перед выполнением рендерингаRenderWatcher компонента GMSkeleton собран в очередь обновленийТаким образом, весь настоящий дом в соответствующем слоте после рендеринга может быть получен в функции обратного вызова NextTick, определенной в это время. Если вы не понимаете принцип NextTick, пожалуйста, перейдитеследующийОтметьте, что вы не знаете
Имя класса операций слотов циклов
handlerComponent(slot, handler/* addSkeletPrefix | removeSkeletPrefix */, init) {
const originchildren = (((slot.componentInstance || {})._vnode || {}).componentOptions || {}).children
const compchildren = ((slot.componentInstance || {})._vnode || {}).children
!init && handler(slot)
if (compchildren) this.handlerPrefix(compchildren, handler, false)
if (originchildren) this.handlerPrefix(originchildren, handler, false)
},
handlerPrefix(slots, handler, init = true) {
slots.forEach(slot => {
var children = slot.children || (slot.componentOptions || {}).children || ((slot.componentInstance || {})._vnode || {}).children
if (slot.data) {
if (!slot.componentOptions) {
!init && handler(slot)
} else if (!this.$hoc_utils.getAbstractComponent(slot)) {
;(function(slot) {
const handlerComponent = this.handlerComponent.bind(this, slot, handler, init)
const insert = (slot.data.hook || {}).insert
;(slot.data.hook || {}).insert = () => { // 函数重构, 修改原有的组件hook, 并且保证insert只执行一次
insert(slot)
handlerComponent()
}
;(slot.data.hook || {}).postpatch = handlerComponent
}).call(this, slot)
}
}
if (slot && slot.elm && slot.elm.nodeType === 3) {
if (this.showSpin) {
slot.memorizedtextContent = slot.elm.textContent
slot.elm.textContent = ''
} else {
slot.elm.textContent = slot.memorizedtextContent || slot.elm.textContent || slot.text
}
}
children && this.handlerPrefix(children, handler, false)
})
},
Пошаговый анализ:
- Перебираем слоты слотов
- Получить набор дочерних элементов под текущим vnode для следующего цикла
- Определите, является ли он родным элементом HTML,Только компонент vnode будет иметь свойство componentOptions
- Чтобы судить о том, является ли абстрактный компонент абстрактным компонентом, мы знаем, что абстрактный компонент не будет отображаться в реальном DOMTree, например, keep-alive, transition и vnode каждого компонента имеет уникальный жизненный цикл хуков:init (инициализация), insert (вставка), prepatch (обновление), destroy (уничтожение), каждый жизненный цикл будет запускаться на разных этапах, захватите вставку, сохраните исходный метод вставки, а затем выполните рефакторинг метода вставки vnode, чтобы вызвать метод handlerComponent внутри, чтобы добавить имя класса, что аналогично концепции использования смонтированный nextTick выше, потому что handlerComponent должен знать экземпляр дочернего компонента,Так что это должно быть вызвано после создания экземпляра, а метод инициализации компонента создаст экземпляр компонента и вызовет непосредственно watcher.update(watcher.render()), то есть, когда мы вызываем метод вставки, он на самом деле происходит после update(render()), поэтому создание экземпляра может быть получено здесь.
- Определите, является ли nodeType текстовым узлом.Если это так, вам нужно сначала сохранить textContent, а затем удалить его.Убедитесь, что текст по умолчанию не отображается при появлении экрана скелета., когда экран скелета исчезнет, верните первоначально зарезервированный текст по умолчанию в vnode, чтобы вы могли свободно переключаться во время отображения и скрытия экрана скелета
Имя статического класса операции vnode
addSkeletPrefix(slot) {
const rootVnode = slot.componentOptions ? (slot.componentInstance || {})._vnode || {} : slot;
if (rootVnode.elm) {
rootVnode.elm.classList.add(this.skeletPrefix)
} else {
;(rootVnode.data || {}).staticClass += ` ${this.skeletPrefix}`
}
},
removeSkeletPrefix(slot) {
const rootVnode = slot.componentOptions ? (slot.componentInstance || {})._vnode || {} : slot;
if (rootVnode.elm) {
rootVnode.elm.classList && rootVnode.elm.classList.remove(this.skeletPrefix)
} else if (rootVnode.data.staticClass) {
rootVnode.data.staticClass = rootVnode.data.staticClass.replace(` ${this.skeletPrefix}`, '')
}
}
addSkeletePrefix используется для добавления имени класса gm-skeleton, а removeSkeletePrefix используется для удаления имени класса gm-skeleton.
инструкции
import Vue from 'vue'
import GMSkeleton from 'path/to/GMSkeleton'
Vue.use(GMSkeleton)
<gm-skeleton>
<Component />
<div></div>
<div><span>前端马丁</span></div>
</gm-skeleton>
передать по значению
| Имя свойства | стоимость | описывать |
|---|---|---|
| showSpin | Boolean | Открывать ли экран скелета, по умолчанию верно |
| skeletPrefix | String | Имя класса экрана Skeleton, по умолчанию gm-skeleton |
Эффект следующий
Конкретный стиль генерируется в соответствии со стилем, написанным самим разработчиком.Он обернут gm-skeleton.Метод использования описан выше.Ниже приведен простой пример.
Полный адрес
80 строк кода для реализации каркасного экрана Vue
заключительные замечания
Надеюсь поставить лайк, приходи и следуй хи хи
Идентификатор WeChat: IAmFinethanksMartin