这篇文章主要介绍了vue实现骨架屏的示例,帮助大家更好的理解和学习使用vue框架,感兴趣的朋友可以了解下
这篇文章主要介绍了vue实现骨架屏的示例,帮助大家更好的理解和学习使用vue框架,感兴趣的朋友可以了解下
这篇文章主要介绍了vue实现骨架屏的示例,帮助大家更好的理解和学习使用vue框架,感兴趣的朋友可以了解下
什么是抽象组件? 在渲染时会被跳过,只做运行时的操作的组件
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是用来执行排序后的更新队列里的所有方法, 在执行render前, GMSkeleton组件的renderWatcher已被收集到更新队列里,所以此时定义nextTick CallBack函数里能获取到渲染后对应插槽里所有真实DOM,若是不了解nextTick原理,请移步你不知道的nextTick
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 = () => { // 函数重构, 修改原有的组件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 ) }) }, |
逐步分析:
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
|
1
2
3
4
5
|
< gm-skeleton > < Component /> < div ></ div > < div >< span >前端马丁</ span ></ div > </ gm-skeleton > |
属性名 | 值 | 描述 |
---|---|---|
showSpin | Boolean | 是否开启骨架屏,默认为true |
skeletPrefix | String | 骨架屏类名, 默认是gm-skeleton |
具体样式是根据开发者自己写的样式来生成的,通过gm-skeleton包裹,如上的使用方法,以下是一个简单的例子
以上就是vue实现骨架屏的示例的详细内容,更多关于vue实现骨架屏的资料请关注米米素材网其它相关文章!
原文链接:https://juejin.cn/post/6954245046690381831
发表评论