一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服務(wù)器之家 - 編程語言 - JavaScript - vue.js - vue實現(xiàn)骨架屏的示例

vue實現(xiàn)骨架屏的示例

2022-03-09 16:26我在曾經(jīng)眺望彼岸 vue.js

這篇文章主要介紹了vue實現(xiàn)骨架屏的示例,幫助大家更好的理解和學(xué)習(xí)使用vue框架,感興趣的朋友可以了解下

骨架屏用途

  • 作為spa中路由切換的 loading, 結(jié)合組件的生命周期和ajax請求返回的時機來使用.( 作為loading 使用)。作為與用戶聯(lián)系最為密切的前端開發(fā)者,用戶體驗是最值得關(guān)注的問題。關(guān)于頁面loading狀態(tài)的展示,主流的主要有l(wèi)oading圖和進度條兩種。除此之外,越來越多的APP采用了“骨架屏”的方式去展示未加載內(nèi)容,給予了用戶煥然一新的體驗。
  • 作為首屏渲染的優(yōu)化

Vue架構(gòu)骨架屏

思路大綱

  • 定義一個抽象組件,在抽象組件的render函數(shù)里獲取插槽
  • 深度循環(huán)遍歷插槽,將每個元素都添加上gm-skeleton的類名
  • 將vnode textContent預(yù)暫后清空保證骨架屏出現(xiàn)時不會出現(xiàn)默認文字
  • 返回slots

定義一個抽象組件

什么是抽象組件? 在渲染時會被跳過,只做運行時的操作的組件

?
1
2
3
4
export default {
  name: 'GmSkeleton',
  abstract: true // 抽象組件的屬性
}

獲取插槽并初始化操作骨架屏

?
1
2
3
4
5
6
7
8
9
10
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是用來執(zhí)行排序后的更新隊列里的所有方法, 在執(zhí)行render前, GMSkeleton組件的renderWatcher已被收集到更新隊列里,所以此時定義nextTick CallBack函數(shù)里能獲取到渲染后對應(yīng)插槽里所有真實DOM,若是不了解nextTick原理,請移步你不知道的nextTick

循環(huán)slots操作類名

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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 = () => { // 函數(shù)重構(gòu), 修改原有的組件hook, 并且保證insert只執(zhí)行一次
            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)
  })
},

逐步分析:

  1. 我們遍歷slots插槽
  2. 獲取當(dāng)前vnode下的children集合以備做下一次循環(huán)
  3. 判斷是否是原生HTML元素,只有組件vnode才會具備componentOptions屬性
  4. 判斷是否抽象組件,我們知道抽象組件是不會渲染到真實DOMTree上的,例如keep-alive、transition,每個組件的vnode擁有獨有的hooks生命周期: init(初始化)、insert(插入)、prepatch(更新)、destroy(銷毀),每個生命周期會在不同階段觸發(fā), 劫持insert,保留原有的insert方法,隨后重構(gòu)vnode的insert方法在里面調(diào)用handlerComponent方法進行添加類名,這里與上面的mounted的nextTick用法理念類似,由于handlerComponent需要知道子組件的實例,所以必須在實例化后去調(diào)用,而組件的init方法會實例組件并且直接調(diào)用watcher.update(watcher.render()), 也就是我們在調(diào)用insert方法的時候其實是在update(render())后,所以這里能夠獲取到實例化后子組件
  5. 判斷nodeType是否是文本節(jié)點,若是的話需要先將textContent保存后進行刪除,保證在骨架屏出現(xiàn)時不會顯示默認文字,在骨架屏消失時,將原先保留的默認文字返回給vnode,這樣就能自由在骨架屏的顯示隱藏期間自由切換

操作vnode的靜態(tài)類名

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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類名,而removeSkeletonPrefix則是用于刪除gm-skeleton類名

使用方法

?
1
2
3
4
import Vue from 'vue'
import GMSkeleton from 'path/to/GMSkeleton'
 
Vue.use(GMSkeleton)
?
1
2
3
4
5
<gm-skeleton>
  <Component />
  <div></div>
  <div><span>前端馬丁</span></div>
</gm-skeleton>

傳值

 

屬性名 描述
showSpin Boolean 是否開啟骨架屏,默認為true
skeletPrefix String 骨架屏類名, 默認是gm-skeleton

 

效果如下

具體樣式是根據(jù)開發(fā)者自己寫的樣式來生成的,通過gm-skeleton包裹,如上的使用方法,以下是一個簡單的例子

vue實現(xiàn)骨架屏的示例

完整地址

80行代碼實現(xiàn)Vue骨架屏

以上就是vue實現(xiàn)骨架屏的示例的詳細內(nèi)容,更多關(guān)于vue實現(xiàn)骨架屏的資料請關(guān)注服務(wù)器之家其它相關(guān)文章!

原文鏈接:https://juejin.cn/post/6954245046690381831

延伸 · 閱讀

精彩推薦
  • vue.jsVue2.x 項目性能優(yōu)化之代碼優(yōu)化的實現(xiàn)

    Vue2.x 項目性能優(yōu)化之代碼優(yōu)化的實現(xiàn)

    這篇文章主要介紹了Vue2.x 項目性能優(yōu)化之代碼優(yōu)化的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋...

    優(yōu)小U9632022-02-21
  • vue.js用vite搭建vue3應(yīng)用的實現(xiàn)方法

    用vite搭建vue3應(yīng)用的實現(xiàn)方法

    這篇文章主要介紹了用vite搭建vue3應(yīng)用的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下...

    Asiter7912022-01-22
  • vue.jsVue多選列表組件深入詳解

    Vue多選列表組件深入詳解

    這篇文章主要介紹了Vue多選列表組件深入詳解,這個是vue的基本組件,有需要的同學(xué)可以研究下...

    yukiwu6752022-01-25
  • vue.js梳理一下vue中的生命周期

    梳理一下vue中的生命周期

    看過很多人講vue的生命周期,但總是被繞的云里霧里,尤其是自學(xué)的同學(xué),可能js的基礎(chǔ)也不是太牢固,聽起來更是吃力,那我就已個人之淺見,以大白話...

    CRMEB技術(shù)團隊7992021-12-22
  • vue.js詳解vue 表單綁定與組件

    詳解vue 表單綁定與組件

    這篇文章主要介紹了vue 表單綁定與組件的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用vue框架,感興趣的朋友可以了解下...

    Latteitcjz6432022-02-12
  • vue.jsVue中引入svg圖標(biāo)的兩種方式

    Vue中引入svg圖標(biāo)的兩種方式

    這篇文章主要給大家介紹了關(guān)于Vue中引入svg圖標(biāo)的兩種方式,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的...

    十里不故夢10222021-12-31
  • vue.jsVue2.x-使用防抖以及節(jié)流的示例

    Vue2.x-使用防抖以及節(jié)流的示例

    這篇文章主要介紹了Vue2.x-使用防抖以及節(jié)流的示例,幫助大家更好的理解和學(xué)習(xí)使用vue框架,感興趣的朋友可以了解下...

    Kyara6372022-01-25
  • vue.jsVue項目中實現(xiàn)帶參跳轉(zhuǎn)功能

    Vue項目中實現(xiàn)帶參跳轉(zhuǎn)功能

    最近做了一個手機端系統(tǒng),其中遇到了父頁面需要攜帶參數(shù)跳轉(zhuǎn)至子頁面的問題,現(xiàn)已解決,下面分享一下實現(xiàn)過程,感興趣的朋友一起看看吧...

    YiluRen丶4302022-03-03
主站蜘蛛池模板: 美女漫画网 | 国产福利不卡 | 千金肉奴隶在线观看 | 国产伦精品一区二区三区女 | 高清一区 | 亚洲 综合 自拍 精品 在线 | 秋霞一级毛片 | 亚洲 欧美 国产 日韩 字幕 | www.99精品视频在线播放 | 色综合精品 | 久久这里只有精品视频e | 国产精品玖玖玖影院 | 7777色鬼xxxx欧美色夫 | 日本sss| 操老逼视频| 亚洲精品一区制服丝袜 | 99久久精品在免费线18 | 美女流白浆 | 国产一卡二卡3卡4卡更新 | 婚色阿花在线全文免费笔 | 四虎永久在线精品国产馆v视影院 | 99热这里只有精品久久免费 | 99精品久久精品一区二区小说 | 动漫人物差差插曲漫画 | 欧美日韩精品乱国产 | 亚洲成人99 | 亚洲羞羞视频 | 国产99视频精品免视看7 | 亚洲国产综合自在线另类 | 黄动漫软件车车好快的车车 | 亚洲精品国产乱码AV在线观看 | 性做久久久久久久 | 午夜私人福利影院 | 免费精品国产在线观看 | 亚洲欧美在线观看一区二区 | 国内体内she精视频免费 | 国产一区二区三区在线看片 | 日本卡1卡2卡4卡免费 | 亚洲图片一区二区 | 男人的天堂久久精品激情 | 国产精品99精品久久免费 |