简介
骨架屏组件Skeleton
罕用于在须要期待加载内容的地位提供一个占位图形组合,能够被 Loading
齐全代替,然而在可用的场景下能够提供更好的视觉效果和用户体验。
- 网络较慢,须要长时间期待加载解决的状况下。
- 图文信息内容较多的列表/卡片中。
- 只在第一次加载数据的时候应用
本文将剖析其源码实现,急躁读完,置信会对您有所帮忙。 组件文档 Skeleton gitee源码
更多组件分析详见 Element 2 源码分析组件总览 。
组件源码
组件的 prop
申明,各属性性能阐明详见官网文档skeleton#attributes 。
根组件 index.vue
根组件定义了两个局部,用于加载占位和实在DOM之间的切换:
- 用于展现骨架屏,提供具名
template
插槽用于自定义占位符。 - 用于展现实在组件UI,应用匿名插槽。
组件应用了v-bind="$attrs"
实现了透传Attributes,用于父子组件的Attributes 继承。
// packages\skeleton\src\index.vue<template> <div> <template v-if="uiLoading"> <!-- 展现骨架屏 --> <div :class="['el-skeleton', animated ? 'is-animated' : '', ]" v-bind="$attrs"> <template v-for="i in count"> <!-- 展现自定义占位符 --> <slot v-if="loading" name="template"> <el-skeleton-item v-for="item in rows" variant="p"/> </slot> </template> </div> </template> <template v-else> <!-- 展现实在 UI --> <slot v-bind="$attrs"></slot> </template> </div></template>
骨架屏占位元素渲染通过外部属性uiLoading
进行管制,该属性逻辑稍后具体介绍。
属性animated
用于生成款式类is-animated
,管制占位元素是否动画成果。
.el-skeleton.is-animated .el-skeleton__item { background: linear-gradient(90deg,#f2f2f2 25%,#e6e6e6 37%,#f2f2f2 63%); background-size: 400% 100%; animation: el-skeleton-loading 1.4s ease infinite}@keyframes el-skeleton-loading { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; }}
占位元素渲染
默认状况下组件会渲染一条记录(属性count
默认值为1),蕴含四个占位元素(属性rows
默认值为4),默认为标签p
款式。
<template v-for="i in count"> <!-- 展现自定义占位符 --> <slot v-if="loading" name="template"> <el-skeleton-item v-for="item in rows" :key="item" :class="{ 'el-skeleton__paragraph': item !== 1, 'is-first': item === 1, 'is-last': item === rows && rows > 1, }" variant="p" /> </slot></template>
首行会被渲染一个长度 33% 的段首;多行时末行会被渲染一个长度 61% 的段尾。
.el-skeleton__p.is-last { width: 61%;}.el-skeleton__p.is-first { width: 33%;}
渲染成果如下图:
当渲染多条数据时,若未未自定义占位元素,会呈现相邻记录的段尾和段首会呈现在一行中(因为应用了<template>
标签),渲染后果如下:
当须要应用骨架屏渲染列表时,才会将 count
设置为多条。
组件生命周期&事件
组件的显示状态uiLoading
依据属性throttle
和loading
传入值动静设置。 当属性 throttle
值大于0,开启提早渲染占位元素,侦听器会进行不同逻辑解决。
watch: { loading: { handler(loading) { // 间接更新加载状态 if (this.throttle <= 0) { this.uiLoading = loading; return; } // 提早更新加载状态 if (loading) { clearTimeout(this.timeoutHandle); // 提早执行 this.timeoutHandle = setTimeout(() => { this.uiLoading = this.loading; }, this.throttle); } else { this.uiLoading = loading; } }, immediate: true }},data() { return { uiLoading: this.throttle <= 0 ? this.loading : false };}
当 API 的申请回来的特地快,往往骨架占位刚刚被渲染,实在的数据就曾经回来了,用户的界面会忽然一闪,此时为了防止这种状况,就须要通过 throttle
属性来防止这个问题。
占位元素组件 item.vue
占位元素组件el-skeleton-item
反对多种标签 p/text/h1/h3/text/caption/button/image/circle/rect
的款式。
// packages\skeleton\src\item.vue<template> <div :class="['el-skeleton__item', `el-skeleton__${variant}`]"> <img-placeholder v-if="variant === 'image'" /> </div></template>
各标签款式渲染成果如下,反对款式自定义:
当须要渲染标签image
款式时应用 svg 图标组件img-placeholder
。
// packages\skeleton\src\img-placeholder.vue<template> <svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"> <path d="M64 896V128h896v768H64z m64-128l192-192 116.352 116.352L640 448l256 307.2V192H128v576z m224-480a96 96 0 1 1-0.064 192.064A96 96 0 0 1 352 288z" /> </svg></template>
组件渲染成果如下:
款式实现
组件款式源码 packages\theme-chalk\src\skeleton.scss
应用混合指令嵌套生成组件款式。
// packages\theme-chalk\src\skeleton.scss// mixin指令 动画成果 @mixin skeleton-color() { // ... animation: #{$namespace}-skeleton-loading 1.4s ease infinite;}// 定义 @keyframes el-skeleton-loading@keyframes #{$namespace}-skeleton-loading { // ... }// 生成 .el-skeleton@include b(skeleton) { // ... // 生成 .el-skeleton__first-line,.el-skeleton__paragraph @each $unit in (first-line, paragraph) { @include e($unit) { // ... } } // 生成 .el-skeleton.is-animated .el-skeleton__item @include when(animated) { .#{$namespace}-skeleton__item { // 混入 占位元素的动画成果 @include skeleton-color(); } }}
组件款式源码 packages\theme-chalk\src\skeleton-item.scss
应用混合指令嵌套生成组件款式。
// packages\theme-chalk\src\skeleton-item.scss// mixin指令 圆形款式@mixin circle-size($size) { // ...}@include b(skeleton) { // 生成 .el-skeleton__item @include e(item) { // ... } // 生成 .el-skeleton__circle @include e(circle) { border-radius: 50%; @include circle-size($--avatar-medium-size); // 生成 .el-skeleton__circle--lg @include m(lg) { @include circle-size($--avatar-large-size); } // 生成 .el-skeleton__circle--md @include m(md) { @include circle-size($--avatar-small-size); } } // 生成 .el-skeleton__p @include e(p) { // ... // 生成 .el-skeleton__p.is-last @include when(last) { width: 61%; } // 生成 .el-skeleton__p.is-first @include when(first) { width: 33%; } } // 生成 .el-skeleton__[button/text/h1/h3/h5/caption] @include e(button) { // ... } // 省略 ... // 生成 .el-skeleton__image @include e(image) { // ... // 生成 .el-skeleton__image svg svg { // ... } } }
依照款式申明,也能够应用标签 h5
款式。圆形尽管定义了不同尺寸,然而组件未提供接口。
参考&关联浏览
'透传Attributes',vuejs
关注专栏
如果本文对您有所帮忙请关注➕、 点赞、 珍藏⭐!您的认可就是对我的最大反对!