第六集-从零开始实现一套pc端vue的ui组件库-loading-组件

34次阅读

共计 3416 个字符,预计需要花费 9 分钟才能阅读完成。

第六集: 从零开始实现(loading 组件)

本集定位 :
loading 组件我相信只要与后端存在交互的项目都是需要它的, 组件虽然简单, 但他的作用十分重要:

  1. 让用户有一个良好的体验, 也就是反馈给用户一个信号, ‘ 我正在做, 再等等 …’.
  2. 遮挡住用户的操作, 也就是此期间 (有可能) 不让用户再去触发其他事件.
  3. 不让用户看到白屏, 看到白屏的体验差到爆炸啊.
  4. 各种炫酷的效果, 也是吸睛的一种手段.

一: loading 需求分析

  1. 出现之时, 要遮挡用户的操作.
  2. 不依赖 dom, 要通过 js 就能控制它的出现与隐藏, 比如配置 axios.
  3. 充满父级, 而不是充满 body, 因为是 pc 端, 所以不是小黑块的形式.

屏幕上方进度条的讨论
我去年的工程里面用的进度条, 体验太差了, 不够显眼, 屏幕上不能点击让人懵圈, 所以本次不用.

骨架屏的讨论
    下一章会做(简易版骨架屏).
很多技术方向, 是为了完美展示 dom 结构的阴影, 1:1 的还原还未加载出的 dom 的样子, 其实我感觉不用这样把 …. 只是个过渡阶段有个大致的样子就可以了, 更多的精力与能力放在业务上, 据我观察了很多 app, 真的 100% 还原的真的不多, 而且我问过很多朋友是否注意到骨架屏与真实的 dom 结构存在偏差, 全都说没注意到, 所以骨架屏这方面本套组件只做最基本的功能.

二: 基础结构的搭建
模板

<template>
// 老规矩:
  <div class="cc-loading">
// 黑色的遮罩层
    <div class="cc-loading__curtain"/>
    // icon 与内容显示区
    <section class="cc-loading__icon">
    // icon 组件
      <ccIcon :name='iconName'
              :color='iconColor' />
    // 显示的提示文字
      <span>{{title}}</span>
    </section>
</template>

js

props: {
    title: {
      type: String,
      default: "加载中 . . ."
    },
    iconName: {  // 加载图标的样子肯定是用户自定义的
      type: String,
      default: "cc-load1" // 默认就是普通的菊花
    },
    iconColor: { // 图标的颜色也是用户自己定的, 万一有特殊需求
      type: String,
      default: "#3F8BDB"
    }
  }

css 部分, 针对居中与定位都有封装.

@import './common/var.scss';
@import './common/extend.scss';
@import './common/mixin.scss';

@include b(loading) {@include position();
    &__curtain{@include position();
    }
    &__icon{
        position: absolute;
        color: $--color-nomal;
        z-index: 10;
        @include flexCenter;
        @include position();
        :nth-child(1){ // 文字与图标分的开一些
            margin-bottom:6px;
        }
    }
}

src/style/common/mixin.scss

@mixin position($position: absolute) {
  margin: auto;
  position: $position;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

@mixin flexCenter {
  display: flex;
  align-items: center;
  flex-direction: column;
  justify-content: center;
}

使用显示

// 需要显示的时候, 让这个 dom 显示即可, 因为默认是对浏览器定位的.
<cc-loading v-if='show' />

三: 针对父级定位, 而不是全局的 loading
其实很简单, 也就是属性的差别, 把 fixed 定位换掉即可, 都可以换上吸附属性浪一浪
让我来加很多友好的属性

<template>
  <div class="cc-loading"
       :style="{'zIndex':boxZIndex,  // 层级'position': position // 定位方式}">
    <div class="cc-loading__curtain"
         :style="{'opacity':opacity, // 这个层的透明度也会友好的让用户填写'background-color':curtainColor  // 颜色也是用户选}" />
    <section class="cc-loading__icon"
          :style="{'fontSize':iconSize+'px'   // 图标的大小}">
      <ccIcon :name='iconName'
              :color='iconColor' />
      <span :style="{'fontSize':textFontSize+'px', // 文字的大小'color':textColor  // 文字的颜色}">{{title}}</span>
    </section>

  </div>
</template>

js, 这里面的默认值都是本套工程的共用值;

 props: {
    position: {
      type: String,
      default: "fixed"
    },
    title: {
      type: String,
      default: "加载中 . . ."
    },
    textColor: {
      type: String,
      default: "#3F8BDB"
    },
    opacity: {
      type: Number,
      default: 0.8
    },
    iconName: {
      type: String,
      default: "cc-load1"
    },
    iconColor: {
      type: String,
      default: "#3F8BDB"
    },
    curtainColor: {
      type: String,
      default: "black"
    },
    boxZIndex: {
      type: Number,
      default: 100
    },
    textFontSize: {
      type: Number,
      default: 17
    },
    iconSize: {
      type: Number,
      default: 25
    }
  },

效果展示

四: 添加事件与 js 编程式调用

其实就算是蒙层状态, 也要给个点击事件, 比如用户点了很多下, 可以给用户弹出一个 ’ 马上好, 再点受不了了 …’, 用户可以自己通过 native 修饰符去做, 但是那样太不工程化了.

<div class="cc-loading"
       @click.stop="onClickLoading">
 onClickLoading() {this.$emit("click");
    }

别忘了加 stop 修饰符, 不然点击穿透可就坏事了.

我们更多时候是要从 js 的方式控制加载状态的
vue-cc-ui/src/components/loading/main/loading.js

// 引入写好的组件
import Loading from './loading.vue';

Loading.install = function(Vue) {
// 注册一下才能使用
  Vue.component(Loading.name, Loading);
// 在原型上挂在一波
  Vue.prototype.$ccShowLoading = function(options) {
// extend 也就是实例化这个组件
    let Constructor = Vue.extend(Loading);
    let node = new Constructor({propsData: options // 所有的配置也都如数传进去});
    // 执行到他的钩子
    node.vm = node.$mount();
    // 插入 body, 因为这个就没必要插入固定的父级了, 用户自己传也可以
    document.body.appendChild(node.$el);
  };
// 有出现就要有消失
  Vue.prototype.$ccHiddenLoading = function() {
   // 从 body 上面找到 class 为这个的元素就干掉.
    document.body.childNodes.forEach(item => {if (item.className === 'cc-loading') {document.body.removeChild(item);
      }
    });
  };
};

export default Loading;

下一章: 简易版骨架屏
欢迎大家一起进步!

github: 链接描述
个人网站: 链接描述

正文完
 0