Element UI 组件源码分析之Spinner加载中

894 阅读2分钟

0x00 简介

组件 Spinner 用于页面和区块的加载中状态,页面局部处于等待异步数据或正在渲染过程时,合适的加载动效会有效缓解用户的焦虑。 本文将深入分析组件源码,剖析其实现原理,耐心读完,相信会对您有所帮助。packages/spinner/src/spinner.vue 文件是组件源码实现。 🔗 github源码 spinner.vue

更多组件分析详见 👉 📚 Element UI 源码剖析组件总览

本专栏的 gitbook 版本地址已经发布 📚《learning element-ui》 ,内容同步更新中!

0x01 Spinner 组件

Spinner.vue 组件是一个隐藏组件,暂未有其他组件使用。

模板创建一个 class 名为el-spinnerspan元素,包含了一个<circle> SVG 圆形。

<template>
  <span class="el-spinner">
    <svg class="el-spinner-inner" viewBox="0 0 50 50" :style="{ width: radius/2 + 'px', height: radius/2 + 'px' }">
      <circle class="path" cx="25" cy="25" r="20" fill="none" :stroke="strokeColor" :stroke-width="strokeWidth"></circle>
    </svg>
  </span>
</template>
<script>
  export default {
    name: 'ElSpinner',
    props: {
      type: String,
      radius: {
        type: Number,
        default: 100
      },
      strokeWidth: {
        type: Number,
        default: 5
      },
      strokeColor: {
        type: String,
        default: '#efefef'
      }
    }
  };
</script> 

组件提供了以下 prop 属性。

参数说明类型默认值
type无效参数string
radiussvg容器大小宽高值 radius/2,单位pxnumber100
strokeWidth图形的轮廓的宽度number5
strokeColor图形的外轮廓的颜色string#efefef

0x02 组件样式

src/spinner.scss

组件样式源码 packages\theme-chalk\src\spinner.scss 使用混合指令 b 嵌套生成组件样式。

// 生成 .el-time-spinner
@include b(time-spinner) {
  // ...
}
// 生成 .el-spinner
@include b(spinner) {
  // ...
}
// 生成 .el-spinner-inner
@include b(spinner-inner) {
  // ...
  
  // 生成 .el-spinner-inner .path
  & .path {
      // ...
    }
}
// 关键帧 CSS动画
@keyframes rotate { /* ...  */ }  
@keyframes dash { /* ...  */ } 

lib/spinner.css

前文可知使用 gulpfile.js编译 scss 文件转换为CSS,经过浏览器兼容、格式压缩,最后生成 packages\theme-chalk\lib\spinner.css,内容格式如下。

.el-time-spinner { /* ...  */ } 
.el-spinner { /* ...  */ } 
.el-spinner-inner { 
  animation: rotate 2s linear infinite;
  width: 50px;
  height: 50px;
}
.el-spinner-inner .path {
  stroke: #ececec;
  stroke-linecap: round; 
  animation: dash 1.5s ease-in-out infinite;
} 
@keyframes rotate { /* ...  */ }  
@keyframes dash { /* ...  */ } 

0x03 CSS 动画

默认的 <circle> 元素展示如下:

image.png

使用 @keyframes at-rule 规则通过在动画序列中定义关键帧(或waypoints)的样式来控制CSS动画序列

定义 <circle>元素动画关键帧规则 dash

@keyframes dash {
  0% {
    stroke-dasharray: 1, 150;
    stroke-dashoffset: 0;
  }
  50% {
    stroke-dasharray: 90, 150;
    stroke-dashoffset: -35;
  }
  100% {
    stroke-dasharray: 90, 150;
    stroke-dashoffset: -124;
  }
}

.el-spinner-inner .path { 
  animation: dash 1.5s ease-in-out infinite;
}

添加动画效果后, <circle>元素展示如下:

spinner1.gif

定义 <svg>元素动画关键帧规则 rotate,用于元素旋转。

@keyframes rotate {
  100% {
    transform: rotate(360deg);
  }
} 

.el-spinner-inner { 
  animation: rotate 2s linear infinite; 
}

添加动画效果后, <svg>元素展示如下:

spinner_svg.gif

组件中不同元素的关键帧效果叠加,实现了 loding 动效。

spinner_c.gif

组件提供了prop 用于自定义效果,代码如下:

<template>
  <el-spinner
    :radius="300"
    :stroke-width="8"
    :stroke-color="'#E6A23C'"
  ></el-spinner>
</template>

组件效果如下:

spinner_ss.gif

由于组件样式 .path 定义了 stroke 属性设置了默认值 #ececec;,导致stroke-color设置无效。需要移除该属性才能生效。

@include b(spinner-inner) {
  // ...

  & .path {
    // stroke: #ececec; 
    stroke-linecap: round;
    animation: dash 1.5s ease-in-out infinite;
  }
}

📚参考&关联阅读

"@keyframes",MDN

关注专栏

如果本文对您有所帮助请关注➕、 点赞👍、 收藏⭐!您的认可就是对我的最大支持!

此文章已收录到专栏中 👇,可以直接关注。