基于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 相关文章推荐
javascript编程起步(第六课)
Feb 27 Javascript
js有序数组的连接问题
Oct 01 Javascript
js向上无缝滚动,网站公告效果 具体代码
Nov 18 Javascript
Google (Local) Search API的简单使用介绍
Nov 28 Javascript
FF IE浏览器修改标签透明度的方法
Jan 27 Javascript
Javascript玩转继承(三)
May 08 Javascript
JavaScript程序设计之JS调试
Dec 09 Javascript
javascript中获取class的简单实现
Jul 12 Javascript
jQuery插件Validation快速完成表单验证的方式
Jul 28 Javascript
微信小程序教程之本地图片上传(leancloud)实例详解
Nov 16 Javascript
Vue.js实现双向数据绑定方法(表单自动赋值、表单自动取值)
Aug 27 Javascript
解决angular2在双向数据绑定时[(ngModel)]无法使用的问题
Sep 13 Javascript
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
配置PHP使之能同时支持GIF和JPEG
2006/10/09 PHP
PHP导入Excel到MySQL的方法
2011/04/23 PHP
php curl基本操作详解
2013/07/23 PHP
WordPress中重置文章循环的rewind_posts()函数讲解
2016/01/11 PHP
Yii2中如何使用modal弹窗(基本使用)
2016/05/30 PHP
PHP有序表查找之插值查找算法示例
2018/02/10 PHP
层序遍历在ExtJs的TreePanel中的应用
2009/10/16 Javascript
Jquery判断$(&quot;#id&quot;)获取的对象是否存在的方法
2013/09/25 Javascript
jquery用offset()方法获得元素的xy坐标
2014/09/06 Javascript
jQuery中scrollLeft()方法用法实例
2015/01/16 Javascript
JS 对象属性相关(检查属性、枚举属性等)
2015/04/05 Javascript
javascript格式化json显示实例分析
2015/04/21 Javascript
JS验证IP,子网掩码,网关和MAC的方法
2015/07/02 Javascript
详解参数传递四种形式
2015/07/21 Javascript
浅谈移动端之js touch事件 手势滑动事件
2016/11/07 Javascript
详解微信小程序入门五: wxml文件引用、模版、生命周期
2017/01/20 Javascript
js仿淘宝评价评分功能
2017/02/28 Javascript
Angular-Ui-Router+ocLazyLoad动态加载脚本示例
2017/03/02 Javascript
在Angular中使用JWT认证方法示例
2018/09/10 Javascript
JS实现的A*寻路算法详解
2018/12/14 Javascript
解决layui表格的表头不滚动的问题
2019/09/04 Javascript
jquery ajax 请求小技巧实例分析
2019/11/11 jQuery
Python 使用PIL中的resize进行缩放的实例讲解
2018/08/03 Python
python创建与遍历List二维列表的方法
2019/08/16 Python
python3 pillow模块实现简单验证码
2019/10/31 Python
python list数据等间隔抽取并新建list存储的例子
2019/11/27 Python
python 代码实现k-means聚类分析的思路(不使用现成聚类库)
2020/06/01 Python
python Paramiko使用示例
2020/09/21 Python
Mansur Gavriel官网:纽约市的一个设计品牌
2019/05/02 全球购物
博士生入学考试推荐信
2013/11/17 职场文书
老人祝寿主持词
2014/03/28 职场文书
国家助学金感谢信
2015/01/21 职场文书
2015年五四青年节演讲稿
2015/03/18 职场文书
在校学生证明格式
2015/06/24 职场文书
农村房屋租赁合同(范本)
2019/07/23 职场文书
python实现简单聊天功能
2021/07/07 Python