基于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 相关文章推荐
window.ActiveXObject使用说明
Nov 08 Javascript
JavaScript之appendChild、insertBefore和insertAfter使用说明
Dec 30 Javascript
让页面上两个div中的滚动条(滑块)同步运动示例
Aug 07 Javascript
javascript模拟枚举的简单实例
Mar 06 Javascript
一行命令搞定node.js 版本升级
Jul 20 Javascript
js锁屏解屏通过对$.ajax进行封装实现
Jul 31 Javascript
JS模拟酷狗音乐播放器收缩折叠关闭效果代码
Oct 29 Javascript
JS实现合并两个数组并去除重复项只留一个的方法
Dec 17 Javascript
原生js获取left值和top值的三种方法
Aug 02 Javascript
JS实现图片旋转动画效果封装与使用示例
Jul 09 Javascript
原生javascript的ajax请求及后台PHP响应操作示例
Feb 24 Javascript
js实现登录时记住密码的方法分析
Apr 05 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生成数组的使用示例 php全组合算法
2014/01/16 PHP
php防止用户重复提交表单
2015/11/02 PHP
PHP对称加密算法(DES/AES)类的实现代码
2017/11/14 PHP
TP框架实现上传一张图片和批量上传图片的方法分析
2020/04/23 PHP
尽可能写&quot;友好&quot;的&quot;Javascript&quot;代码
2007/01/09 Javascript
js 字符串操作函数
2009/07/25 Javascript
关于event.cancelBubble和event.stopPropagation()的区别介绍
2011/12/11 Javascript
用js判断页面刷新或关闭的方法(onbeforeunload与onunload事件)
2012/06/22 Javascript
js获取url参数值的两种方式
2013/09/10 Javascript
使用原生js写的一个简单slider
2014/04/29 Javascript
JS模拟实现Select效果代码
2015/09/24 Javascript
简单谈谈javascript中this的隐式绑定
2016/02/22 Javascript
浅谈jQuery绑定事件会叠加的解决方法和心得总结
2016/10/26 Javascript
js实现表格筛选功能
2017/01/18 Javascript
原生js实现吸顶效果
2017/03/13 Javascript
通过V8源码看一个关于JS数组排序的诡异问题
2017/08/14 Javascript
cnpm加速Angular项目创建的方法
2018/09/07 Javascript
vue 刷新之后 嵌套路由不变 重新渲染页面的方法
2018/09/13 Javascript
ExtJs使用自定义插件动态保存表头配置(隐藏或显示)
2018/09/25 Javascript
基于VUE实现简单的学生信息管理系统
2021/01/13 Vue.js
[02:04]2018DOTA2亚洲邀请赛Secret赛前采访
2018/04/03 DOTA
Python中Continue语句的用法的举例详解
2015/05/14 Python
python对象及面向对象技术详解
2016/07/19 Python
Python tkinter实现的图片移动碰撞动画效果【附源码下载】
2018/01/04 Python
Python元组及文件核心对象类型详解
2018/02/11 Python
Python RabbitMQ消息队列实现rpc
2018/05/30 Python
python画图的函数用法以及技巧
2019/06/28 Python
AUC计算方法与Python实现代码
2020/02/28 Python
详解用Python爬虫获取百度企业信用中企业基本信息
2020/07/02 Python
日本热销NO.1胶原蛋白冻:Aishitoto爱希特多
2019/06/20 全球购物
Java基础面试题
2012/11/02 面试题
《月光启蒙》教学反思
2014/03/01 职场文书
有限责任公司股东合作协议书
2014/12/02 职场文书
教师个人年终总结
2015/02/11 职场文书
数学备课组工作总结
2015/08/12 职场文书
2015年教师党员个人总结
2015/11/24 职场文书