vue實現骨架屏的示例
阿新 • • 發佈:2021-04-26
骨架屏用途
- 作為spa中路由切換的 loading,結合元件的生命週期和ajax請求返回的時機來使用.( 作為loading 使用)。作為與使用者聯絡最為密切的前端開發者,使用者體驗是最值得關注的問題。關於頁面loading狀態的展示,主流的主要有loading圖和進度條兩種。除此之外,越來越多的APP採用了“骨架屏”的方式去展示未載入內容,給予了使用者煥然一新的體驗。
- 作為首屏渲染的優化
vue架構骨架屏
思路大綱
- 定義一個抽象元件,在抽象元件的render函式裡獲取插槽
- 深度迴圈遍歷插槽,將每個元素都新增上gm-skeleton的類名
- 將vnode textContent預暫後清空保證骨架屏出現時不會出現預設文字
- 返回slots
定義一個抽象元件
什麼是抽象元件? 在渲染時會被跳過,只做執行時的操作的元件
export def程式設計客棧ault {
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 }
這裡我們將處理slots的方法放置在nextTick裡面,因為handlerPrefix裡需要獲取真實的DOM,nextTick是用來執行排序後的更新佇列裡的所有方法,在執行render前,GMSkeleton元件的renderWatcher已被收集到更新佇列裡,所以此時定義nextTick CallBack函式裡能獲取到渲染後對應插槽裡所有真實DOM,若是不瞭解nextTick原理,請移步你不知道的nextTick
迴圈slots操作類名
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,false) },handlerPrefix(slots,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,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 { BdEbjeXksK slot.elm.textContent = slot.memorizedtextContent || slot.elm.textContent || slot.text } } children && this.handlerPrefix(children,false) }) },
逐步分析:
- 我們遍歷slots插槽
- 獲取當前vnode下的children集合以備做下一次迴圈
- 判斷是否是原生HTML元素,只有元件vnode才會具備componentOptions屬性
- 判斷是否抽象元件,我們知道抽象元件是不會渲染到真實DOMTree上的,例如keep-alive、transition,每個元件的vnode擁有獨有的hooks生命週期: init(初始化)、insert(插入)、prepatch(更新)、destroy(銷燬),每個生命週期會在不同階段觸發,劫持insert,保留原有的insert方法,隨後重構vnode的insert方法在裡面呼叫handlerComponent方法進行新增類名,這裡與上面的mounted的nextTick用法理念類似,由於handlerComponent需要知道子元件的例項,所以必須在例項化後去呼叫,而元件的init方法會例項元件並且直接呼叫watcher.update(watcher.render()),也就是我們在呼叫insert方法的時候其實是在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 && rohttp://www.cppcns.comotVnode.elm.classList.remove(this.skeletPrefix) } else if (rootVnode.data.staticClass) { rootVnode.data.staticClass = rootVnode.data.staticClass.replace(` ${this.skeletPrefix}`,'') } }
addSkeletePrefix用於新增gm-skeleton類名,而removeSkeletonPrefix則是用於刪除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 | 是否開啟骨架屏,預設為true |
skeletPrefix | String | 骨架屏類名,預設是gm-skeleton |
效果如下
具體樣式是根據開發者自己寫的樣式來生成的,通過gm-skeleton包裹,如上的使用方法,以下是一個簡單的例子
完整地址
80行程式碼實現Vue骨架屏
以上就是vue實現骨架屏的示例的詳細內容,更多關於vue實現骨架www.cppcns.com屏的資料請關注我們其它相關文章!