《精通react/vue组件设计》之5分钟教你实现一个极具创意的加载(Loading)组件

徐小夕 等级 326 0 0

前言

本文是笔者写组件设计的第八篇文章, 今天带大家用5分钟实现一个极具创意的加载(loading)组件.涉及的核心知识点主要是css3相关特性, 如果大家非常熟悉,可直接跳过介绍直接看正文.

时刻问自己:是否具备创造力?

[笔记]前端组件的一般分类:

  • 通用型组件: 比如Button, Icon等.
  • 布局型组件: 比如Grid, Layout布局等.
  • 导航型组件: 比如面包屑Breadcrumb, 下拉菜单Dropdown, 菜单Menu等.
  • 数据录入型组件: 比如form表单, Switch开关, Upload文件上传等.
  • 数据展示型组件: 比如Avator头像, Table表格, List列表等.
  • 反馈型组件: 比如Progress进度条, Drawer抽屉, Modal对话框等.
  • 其他业务类型

所以我们在设计组件系统的时候可以参考如上分类去设计,该分类也是antd, element, zend等主流UI库的分类方式.

如果对于react/vue组件设计原理不熟悉的,可以参考我的之前写的组件设计系列文章:

笔者已经将组件库发布到npm上了, 大家可以通过npm安装的方式体验组件.

正文

在开始组件设计之前希望大家对css3和js有一定的基础,并了解基本的react/vue语法.我们先看看实现后的组件效果: 《精通react/vue组件设计》之5分钟教你实现一个极具创意的加载(Loading)组件 《精通react/vue组件设计》之5分钟教你实现一个极具创意的加载(Loading)组件 《精通react/vue组件设计》之5分钟教你实现一个极具创意的加载(Loading)组件 因为动图体积太大,就不给大家传gif了,接下来我们具体分析一下该组件的特点.

1. 组件设计思路

按照之前笔者总结的组件设计原则,我们第一步是要确认需求. 首先我们设计的不是后台管理系统专用的加载动画,而是作为一个C端产品的功用型加载动画.我们都知道加载动画的作用是:在用户等待网页时能看到有用的信息,比如网站介绍,引导, 公司信息等,缓解用户焦虑. 作为一名产品经理或者用户体验师, 这种个性化的加载体验效果往往是更好的.

而加载动画一般会分为策略型加载动画和通用加载动画,通用加载动画我就不说了,大家平时做的系统大部分应该都是通用型加载动画. 我这里介绍一下策略型加载动画: 策略型加载动画往往用在C端产品或者系统中,用来为用户提供更多的引导信息, 当用户首次访问系统或者网站时, 由于某种主动型引导(网站在加载时或者切换页面时故意给用户看到的加载信息)或者环境原因(网络,带宽限制导致的加载过慢,此时出现加载动画), 这些加载信息往往带有某种用途,比如对于个人博客网站, 这个加载动画可以是博主的介绍,博主的宣传信息,github地址等, 对于企业来说,可能是某个新功能的介绍, 网站服务信息的介绍,联系方式等.

在了解完以上背景后, 我们来看看组件设计的线框图: 《精通react/vue组件设计》之5分钟教你实现一个极具创意的加载(Loading)组件 对于react选手来说,如果没用typescript,建议大家都用PropTypes, 它是react内置的类型检测工具,我们可以直接在项目中导入. vue有自带的属性检测方式,这里就不一一介绍了.

通过以上需求分析, 其实一个加载动画非常简单, 不会涉及到太多功能, 主要在于css3动画的使用. 具体属性有:

  • 加载动画出现时的加载文本
  • 控制加载状态的state

接下来我们就来看看具体实现.

2. 基于react实现一个Loading组件

因为该组件不会涉及到太多的js代码,主要是html和css,所以我们直接先构建组件的结构:

/**
 * 骨架屏组件(SEO)
 * @param {isLoading} bool 加载状态
 * @param {loadingText} string 加载时的加载文本
 */
export default function Skeleton(props) {
  let { isLoading = true, loadingText = '正在为您疯狂加载...' } = props
  return isLoading ? <div className={styles.skeletonWrap}>
    <div className={styles.skeletonContent} data-loadingText={loadingText}>
      自定义的引导内容
    </div>
  </div> : null
}

自定义的引导内容这里我就不介绍了, 主要根据不同的网站性质灵活配置.我主要介绍加载动画部分, 其实原理也很简单, 我们在skeletonContent元素上使用一个::after伪对象来实现窗帘动画即可.

在实现动画前大家最好对关键帧动画有所了解,我相信大家都比较了解. 这种关窗帘动画一种实现方式就是通过控制元素宽度, 从0到100%, 然后添加适当的要是优化即可. 动画的代码如下:

@keyframes spread {
  0% {
    width: 0;
  }
  100% {
    width: 100%;
  }
}

我们只需要在::after里直接这样使用就好了:

&::after {
  animation: spread 18s 3s infinite;
}

这样动画已经做完了, 但是为了让动画更完整,我们还要考虑一个事实, 如果窗帘宽度从0慢慢变化的过程中, 加载动画的文字一直保持一个颜色会很生硬, 如下图: 《精通react/vue组件设计》之5分钟教你实现一个极具创意的加载(Loading)组件 所以说作为一个好的交互设计来说, 要让交互体验更顺畅,这里提供一种方式,就是加载的文本在窗帘宽度变化的同时,文字的透明度从0变化到1,这样就会柔和很多, 所以动画可以这么改:

&::after {
  color: rgba(255, 255, 255, 0);
  animation: spread 18s infinite;
}
@keyframes spread {
  0% {
    width: 0;
    color: rgba(255, 255, 255, 0);
  }
  100% {
    width: 100%;
    color: rgba(255, 255, 255, 1);
  }
}

效果如下: 《精通react/vue组件设计》之5分钟教你实现一个极具创意的加载(Loading)组件

最后我们来实现loadingText. 这块也涉及到一个知识点, 因为加载文本其实主要是用来修饰元素的,并没有太多的语义化场景, 所以我们会放在::after伪对象的content里, 但是一般content是在css里写的,那么如何实现动态文本呢? 我们这里就要采用css的属性内容这个api. content不仅仅可以接收一个字符串,还可以接收attr这个关键字,关键字里面的内容是元素的自定义属性, 比如:

<div data-tip="loading"></div>

那么我们在css里可以通过这种方式直接使用data-tip属性的值:

div::after{
    content: attr(data-tip)
}

通过以上的方式我们可以在::after里直接拿到data-tip的内容了, content其实还有更多的功能,比如用纯css实现一个计数器,大家可以研究学习一下.

这样,我们的Loading组件就完成了, 还有一个问题是我代码里的组件命名,为什么叫骨架屏呢?其实我们只要改变内容结构, 它立马就可以变成一个骨架屏,所以命名这块可以按照实际需求来确定.

3. 健壮性支持, 我们采用react提供的propTypes工具:

import PropTypes from 'prop-types'
// ...
Skeleton.propTypes = {
  isLoading: PropTypes.bool,
  loadingText: PropTypes.string
}

组件完整css代码如下:

.skeletonWrap {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  background-color: rgba(0,0,0, .6);
  .skeletonContent {
    position: relative;
    margin: 200px auto 0;
    padding: 20px;
    width: 800px;
    display: flex;
    align-items: center;
    border-radius: 8px;
    overflow: hidden;
    background-color: #fff;
    &::after {
      content: '正在为您疯狂加载...';
      position: absolute;
      top: 0;
      left: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      width: 0;
      height: 100%;
      border-right: 2px solid #ccc;
      box-shadow: 0 0 8px #000;
      background: #096;
      color: rgba(255, 255, 255, 0);
      font-size: 24px;
      white-space: nowrap;
      animation: spread 18s 3s infinite;
    }
    @keyframes spread {
      0% {
        width: 0;
        color: rgba(255, 255, 255, 0);
      }
      100% {
        width: 100%;
        color: rgba(255, 255, 255, 1);
      }
    }

    .imgBox {
      margin-right: 20px;
      width: 400px;
      .img {
        width: 100%;
        height: 200px;
        background-color: #ccc;
      }
      img {
        width: 100%;
      }
    }
    .rightBox {
      flex: 1;
      .tit {
        margin-top: 8px;
        margin-bottom: 8px;
        font-size: 22px;
      }
      .labelWrap {
        span {
          margin: 3px;
          display: inline-block;
          font-size: 12px;
          padding: 2px 6px;
          border-radius: 3px;
          color: #fff;
          background-color: #58bd6b;
        }
      }
      .desc {
        color: rgb(44, 44, 44);
        font-size: 14px;
      }
    }
  }
}

关于代码中的css module和classnames的使用大家可以自己去官网学习,非常简单.如果不懂的可以在评论区提问,笔者看到后会第一时间解答.

4 使用Skeleton组件

我们可以通过如下方式使用它:

<Skeleton loadingText="玩命加载中..." />

笔者已经将实现过的组件发布到npm上了,大家如果感兴趣可以直接用npm安装后使用,方式如下:

npm i @alex_xu/xui

// 导入xui
import { 
  Button,
  Skeleton,
  Empty,
  Progress,
  Tag,
  Switch,
  Drawer,
  Badge,
  Alert
} from '@alex_xu/xui'

该组件库支持按需导入,我们只需要在项目里配置babel-plugin-import即可,具体配置如下:

// .babelrc
"plugins": [
  ["import", { "libraryName": "@alex_xu/xui", "style": true }]
]

npm库截图如下:

《精通react/vue组件设计》之5分钟教你实现一个极具创意的加载(Loading)组件

最后

后续笔者将会继续实现

  • modal(模态窗),
  • badge(徽标),
  • table(表格),
  • tooltip(工具提示条),
  • Skeleton(骨架屏),
  • Message(全局提示),
  • form(form表单),
  • switch(开关),
  • 日期/日历,
  • 二维码识别器组件

等组件, 来复盘笔者多年的组件化之旅.

如果想获取组件设计系列完整源码, 或者想学习更多H5游戏, webpacknodegulpcss3javascriptnodeJScanvas数据可视化等前端知识和实战,欢迎在公号《趣谈前端》加入我们的技术群一起学习讨论,共同探索前端的边界。

《精通react/vue组件设计》之5分钟教你实现一个极具创意的加载(Loading)组件

更多推荐

收藏
评论区

相关推荐

为什么 React 源码不用 TypeScript 来写?
周末的,看点轻松的吧,之前看过 React 的源码,比较好奇像 React 这样庞大的工程为什么没有用 TypeScript。 Facebook 工程师 Cat Chen 在知乎上(https://www.zhihu.com/question/378470381/answer/1079675543(https://www.zhihu.com/quest
教你用200行代码写一个爱豆拼拼乐H5小游戏(附源码)
前言 本文将带大家一步步实现一个H5拼图小游戏,考虑到H5游戏的轻量级和代码体积,我没有使用react或vue这些框架,而采用我自己写的dom库和原生javascript来实现业务功能,具体库代码可见我的文章如何用不到200行代码写一款属于自己的js类库(https://juejin.im/post/6844903880707293198),构建工具我采
vue-toy: 200行代码模拟Vue实现
vuetoy 200行左右代码模拟vue实现,视图渲染部分使用React来代替Sanbbdom,欢迎Star。 项目地址:https://github.com/bplok20010/vuetoy(https://github.com/bplok20010/vuetoy) codesandbox示例(https://codes
前端组件/库打包利器rollup使用与配置实战
目前主流的前端框架vue和react都采用rollup来打包,为了探索rollup的奥妙,接下来就让我们一步步来探索,并基于rollup搭建一个库打包脚手架,来发布自己的库和组件。 (https://imghelloworld.osscnbeijing.aliyuncs.com/imgs/16cb1c297071015523fb08d9e0f
基于jsoneditor二次封装一个可实时预览的json编辑器组件(react版)
前言 做为一名前端开发人员,掌握vue/react/angular等框架已经是必不可少的技能了,我们都知道,vue或react等MVVM框架提倡组件化开发,这样一方面可以提高组件复用性和可扩展性,另一方面也带来了项目开发的灵活性和可维护,方便多人开发协作.接下来文章将介绍如何使用react,开发一个自定义json编辑器组件.我们这里使用了jsoneditor
《精通react/vue组件设计》之用纯css打造类materialUI的按钮点击动画并封装成react组件
前言 作为一个前端框架的重度使用者,在技术选型上也会非常注意其生态和完整性.笔者先后开发过基于vue,react,angular等框架的项目,碧如vue生态的elementUI, antdesignvue, iView等成熟的UI框架, react生态的antdesign, materialUI等,这些第三方UI框架极大的降低了我们开发一个项目的成本和
《精通react/vue组件设计》之配合React Portals实现一个功能强大的抽屉(Drawer)组件
前言 本文是笔者写组件设计的第六篇文章,内容依次从易到难,今天会用到react的高级API React Portals,它也是很多复杂组件必用的方法之一. 通过组件的设计过程,大家会接触到一个完成健壮的组件设计思路和方法,也能在实现组件的过程逐渐对react/vue的高级知识和技巧有更深的理解和掌握,并且在企业实际工作做游刃有余. 之所以会写组件设计相关
《精通react/vue组件设计》之5分钟教你实现一个极具创意的加载(Loading)组件
前言 本文是笔者写组件设计的第八篇文章, 今天带大家用5分钟实现一个极具创意的加载(loading)组件.涉及的核心知识点主要是css3相关特性, 如果大家非常熟悉,可直接跳过介绍直接看正文. 时刻问自己:是否具备创造力? 笔记前端组件的一般分类: 通用型组件: 比如Button, Icon等. 布局型组件: 比如Grid, Layout布
Angular vs React 最全面深入对比
Angular vs React 最全面深入对比 Angular vs React 最全面深入对比 本文参考文章:https://www.sitepoint.com/reactvsangul
Taro 入门教程
简介 Taro 是一个遵循 React 语法规范的开放式跨端跨框架解决方案,支持使用 React/Vue/Nerv 等框架来开发微信/京东/百度/
MobX 上手指南
之前用 Redux 比较多,一直听说 Mobx 能让你体验到在 React 里面写 Vue 的感觉,今天打算尝试下 Mobx 是不是真的有写 Vue 的感觉。 题外话 在介绍 MobX 的用法之前,先说点题外话,我们可以看一下 MobX 的中文简介。在 MobX 的中文网站上写着: MobX 是一个经过战火洗礼的库,它通过透明的函数响应式编程
【Flutter实战】状态管理
3.2 状态管理响应式的编程框架中都会有一个永恒的主题——“状态(State)管理”,无论是在React/Vue(两者都是支持响应式编程的Web开发框架)还是Flutter中,他们讨论的问题和解决的思想都是一致的。所以,如果你对React/Vue的状态管理有了解,可以跳过本节。言归正传,我们想一个问题,StatefulWidget的状态应该被谁管理?
新手学习 React 迷惑的点
网上各种言论说 React 上手比 Vue 难,可能难就难不能深刻理解 JSX,或者对 ES6 的一些特性理解得不够深刻,导致觉得有些点难以理解,然后说 React 比较难上手,还反人类啥的,所以我打算写两篇文章来讲新手学习 React 的时候容易迷惑的点写出来,如果你还以其他的对于学习 React 很迷惑的点,可以在留言区里给我留言。为什么要引入 Reac
2021前端技术面试必备Vue:(四)Vuex状态管理
前三章陆续已经更新了Vue基本使用 和Vue Router的基本使用,如果你读了前三篇文章的话,并且掌握差不多,那么你现在可以开发简单的应用了,例如Blog,电商网站........唯一不足的是,随着你的业务需求不断增加,页面中的状态数据也不断庞大,维护起来就特别困难了,Vue 提供了一种状态管理 解决办法 Vuex,它的思想和React 的R
【单例深思】饿汉式
1、抛出问题1. 为什么饿汉式单例是线程安全的?2. 为什么饿汉式单例没有延迟加载(Lazy Loading)? 2、JVM类加载机制饿汉式单例的实现:javapublic class Singleton private static Singleton singleton new Singleton(); private S