基于Vue 实现一个中规中矩loading组件


Posted in Javascript onApril 03, 2019

前言

最近有一个新的项目,UI大佬不知道从哪里找来了一张GIF丢到蓝湖,说作为全局的页面loading ,但是自己想了想,还是选择画一个。

一开始想过用svg,canvas;最终还是选择了css3+js来实现这个效果;

gif的缺点挺多,至于为什么又排除了svg和canvas;

是因为css3+js可控性更强,不管是大小还是颜色,还是响应式(我的项目走的vh,vw)那套来适配;

可以借助打包插件,达到loading的大小适配;

效果

UI大佬提供的GIF

基于Vue 实现一个中规中矩loading组件

实现的效果【在线codesandbox预览】

基于Vue 实现一个中规中矩loading组件

  • 支持环的颜色改变及整个展示大小
  • 支持在loading底部显示文字并控制其样式

实现思路

这个东东主要用了这么几个要点来实现完整的效果;

  • flex和position来布局
  • 伪类的颜色继承(currentColor)
  • 边框结合圆角实现环
  • 用了transform和animation来实现了整个过渡

效果知道怎么实现了,剩下的就是我们需要实现的功能点了;

因为是面向移动端的,所以这些常规的东东也要考虑下

  • 遮罩层可控
  • 防止点击穿透滚动body
  • 组件支持函数方法调用

源码

Loading.vue

<template>
 <div id="loading-wrapper">
 <div class="loading-ring" :style="ringStyle">
  <div class="outer" />
  <div class="middle" />
  <div class="inner" />
 </div>
 <div class="text" :style="textStyle" v-if="text">
  {{ text }}
 </div>
 </div>
</template>

<script>
export default {
 name: "Loading",
 props: {
 text: {
  type: String,
  default: ""
 },
 textStyle: {
  type: Object,
  default: function() {
  return {
   fontSize: "14px",
   color: "#fff"
  };
  }
 },
 ringStyle: {
  type: Object,
  default: function() {
  return {
   width: "100px",
   height: "100px",
   color: "#407af3"
  };
  }
 }
 },
 methods: {
 preventDefault(e) {
  // 禁止body的滚动
  console.log(e);
  e.preventDefault();
  e.stopPropagation();
 }
 },
 mounted() {
 document
  .querySelector("body")
  .addEventListener("touchmove", this.preventDefault);
 },
 destroyed() {
 document
  .querySelector("body")
  .removeEventListener("touchmove", this.preventDefault);
 }
};
</script>

<style lang="scss" scoped>
#loading-wrapper {
 position: fixed;
 left: 0;
 top: 0;
 height: 100vh;
 width: 100vw;
 background-color: rgba(0, 0, 0, 0.25);
 display: flex;
 justify-content: center;
 align-items: center;
 flex-direction: column;
 .loading-ring {
 position: relative;
 width: 200px;
 height: 200px;
 .outer,
 .inner,
 .middle {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  color: currentColor;
  &::after {
  content: "";
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 100%;
  border-left: 10px solid currentColor;
  border-right: 10px solid currentColor;
  border-top: 10px solid currentColor;
  border-bottom: 10px solid transparent;
  }
 }

 .outer {
  width: 100%;
  height: 100%;
  &::after {
  animation: anticlockwise 1.5s infinite linear;
  }
 }
 .inner {
  width: calc(100% * 0.6);
  height: calc(100% * 0.6);
  &::after {
  animation: anticlockwise 1.5s infinite linear;
  }
 }
 .middle {
  width: calc(100% * 0.8);
  height: calc(100% * 0.8);
  &::after {
  animation: clockwise 1.5s infinite linear;
  }
 }
 }

 .text {
 color: #fff;
 font-size: 14px;
 padding: 30px;
 width: 250px;
 text-align: center;
 }
}

@keyframes clockwise {
 0% {
 transform: rotate(0deg);
 }
 100% {
 transform: rotate(360deg);
 }
}
@keyframes anticlockwise {
 0% {
 transform: rotate(0deg);
 }
 100% {
 transform: rotate(-360deg);
 }
}
</style>

index.js

import Loading from "./Loading.vue";
// 来保持实例,单例模式
let instance;
let el;

Loading.install = function(Vue, options = {}) {
 const defaultOptions = {
 text: "",
 textStyle: {
  fontSize: "14px",
  color: "#fff"
 },
 ringStyle: {
  width: "100px",
  height: "100px",
  color: "#407af3"
 },
 ...options
 };
 Vue.prototype.$loading = {
 show(options = {}) {
  if (!instance) {
  let LoadingInstance = Vue.extend(Loading);
  el = document.createElement("div");
  document.body.appendChild(el);
  instance = new LoadingInstance({
   propsData: { defaultOptions, ...options }
  }).$mount(el);
  } else {
  return instance;
  }
 },
 hide() {
  if (instance) {
  document.body.removeChild(document.getElementById("loading-wrapper"));
  instance = undefined;
  }
 }
 };
};

export default Loading;

选项及用法

选项

text: { // 这个不为空就在loading下面显示文字
  type: String,
  default: ""
 },
 textStyle: { // loading text 的样式,颜色及字体大小
  type: Object,
  default: function() {
  return {
   fontSize: "14px",
   color: "#fff"
  };
  }
 },
 ringStyle: { // 最外环的大小,内二环是比例换算的(百分比)
  type: Object,
  default: function() {
  return {
   width: "100px",
   height: "100px",
   color: "#407af3"
  };
  }
 }

用法

在主入口use一下便可全局使用

除了常规的引入使用,还支持函数调用,挂载了一个$loading。

this.$loading.show({
  text: "loading",
  textStyle: {
   fontSize: "18px",
   color: "#f00"
  }
  });
  
let st = setTimeout(() => {
  clearTimeout(st);
  this.$loading.hide();
 }, 1000);

总结

props的传递没有做增量合并(递归每个key赋值),直接浅复制合并的对于组件功能的概而全,拓展性,大小需要自己权衡;

到这里,我们业务需要的一个小组件,该有的功能都有了。

以上所述是小编给大家介绍的基于Vue 实现一个中规中矩loading组件,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
共享自己写一个框架DreamScript
Jan 20 Javascript
jQuery学习笔记[1] jQuery中的DOM操作
Dec 03 Javascript
Yii-自定义删除确认弹框(zyd)jquery实现代码
Mar 04 Javascript
js实现时间显示几天前、几小时前或者几分钟前的方法集锦
May 29 Javascript
jQuery往textarea中光标所在位置插入文本的方法
Jun 26 Javascript
跟我学习javascript的函数调用和构造函数调用
Nov 16 Javascript
JavaScript中的Number数字类型学习笔记
May 26 Javascript
详解webpack3如何正确引用并使用jQuery库
Aug 26 jQuery
bootstrap日期插件daterangepicker使用详解
Oct 19 Javascript
vue 实现边输入边搜索功能的实例讲解
Sep 16 Javascript
详解JSON和JSONP劫持以及解决方法
Mar 08 Javascript
vue-router中hash模式与history模式的区别
Jun 23 Vue.js
javascript实现小型区块链功能
Apr 03 #Javascript
vue插槽slot的理解和使用方法
Apr 03 #Javascript
react写一个select组件的实现代码
Apr 03 #Javascript
vue框架下部署上线后刷新报404问题的解决方案(推荐)
Apr 03 #Javascript
JavaScript变速动画函数封装添加任意多个属性
Apr 03 #Javascript
JS中注入eval, Function等系统函数截获动态代码
Apr 03 #Javascript
性能优化篇之Webpack构建速度优化的建议
Apr 03 #Javascript
You might like
SONY ICF-SW07收音机电路分析
2021/03/02 无线电
php 读取文件乱码问题
2010/02/20 PHP
UCenter中的一个可逆加密函数authcode函数代码
2010/07/20 PHP
PHP 获取文件路径(灵活应用__FILE__)
2013/02/15 PHP
JQuery 拾色器插件发布-jquery.icolor.js
2010/10/20 Javascript
ie8 不支持new Date(2012-11-10)问题的解决方法
2013/07/31 Javascript
JS字符串的切分用法实例
2016/02/22 Javascript
Windows系统下安装Node.js的步骤图文详解
2016/11/15 Javascript
js验证手机号、密码、短信验证码代码工具类
2020/06/24 Javascript
vue.js实现数据动态响应 Vue.set的简单应用
2017/06/15 Javascript
[原创]jQuery实现合并/追加数组并去除重复项的方法
2018/04/11 jQuery
JS获取子节点、父节点和兄弟节点的方法实例总结
2018/07/06 Javascript
js中null与空字符串&quot;&quot;的区别讲解
2019/01/17 Javascript
如何换个角度使用VUE过滤器详解
2019/09/11 Javascript
Vue.directive 实现元素scroll逻辑复用
2019/11/29 Javascript
Vue自定义组件的四种方式示例详解
2020/02/28 Javascript
wxpython中利用线程防止假死的实现方法
2014/08/11 Python
python网络编程之读取网站根目录实例
2014/09/30 Python
一步步教你用Python实现2048小游戏
2017/01/19 Python
python3.6 如何将list存入txt后再读出list的方法
2019/07/02 Python
python通过opencv实现图片裁剪原理解析
2020/01/19 Python
python GUI库图形界面开发之PyQt5开发环境配置与基础使用
2020/02/25 Python
如何基于Django实现上下文章跳转
2020/09/16 Python
迪斯尼商品官方网站:ShopDisney
2016/08/01 全球购物
英国露营设备和户外服装购物网站:Simply Hike
2019/05/05 全球购物
Linux中如何用命令创建目录
2015/01/12 面试题
眼镜促销方案
2014/03/15 职场文书
学历公证委托书
2014/04/09 职场文书
2015年感恩节活动总结
2015/03/24 职场文书
论文评审意见
2015/06/05 职场文书
消防安全培训工作总结
2015/10/23 职场文书
如何获取numpy array前N个最大值
2021/05/14 Python
Java网络编程之UDP实现原理解析
2021/09/04 Java/Android
正则表达式拆分url实例代码
2022/02/24 Java/Android
Java存储没有重复元素的数组
2022/04/29 Java/Android
Flink 侧流输出源码示例解析
2022/09/23 Servers