基于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类和继承 this属性使用说明
Sep 03 Javascript
某人初学javascript的时候写的学习笔记
Dec 30 Javascript
js获取会话框prompt的返回值的方法
Jan 10 Javascript
js中键盘事件实例简析
Jan 10 Javascript
Jquery Ajax Error 调试错误的技巧
Nov 20 Javascript
Javascript blur与click冲突解决办法
Jan 09 Javascript
彻底理解js面向对象之继承
Feb 04 Javascript
vue axios请求拦截实例代码
Mar 29 Javascript
jQuery实现的响应鼠标移动方向插件用法示例【附源码下载】
Aug 28 jQuery
详解基于node.js的脚手架工具开发经历
Jan 28 Javascript
微信小程序简单的canvas裁剪图片功能详解
Jul 12 Javascript
elementui实现预览图片组件二次封装
Dec 29 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读取TXT文件向数据库导入海量数据的方法
2013/04/23 PHP
php站内搜索关键词变亮的实现方法
2014/12/30 PHP
PHP date函数常用时间处理方法
2015/05/11 PHP
WAF的正确bypass
2017/01/05 PHP
Javascript 日期处理之时区问题
2009/10/08 Javascript
JavaScript 面向对象编程(1) 基础
2010/05/18 Javascript
jQuery获取浏览器中的分辨率实现代码
2013/04/23 Javascript
一个简单的弹性返回顶部JS代码实现介绍
2013/06/09 Javascript
JS.elementGetStyle(element, style)应用示例
2013/09/24 Javascript
点击页面其它地方隐藏该div的两种思路
2013/11/18 Javascript
IE与FireFox的JavaScript兼容问题解决办法
2013/12/31 Javascript
javascript实现table表格隔行变色的方法
2015/05/13 Javascript
jquery append 动态添加的元素事件on 不起作用的解决方案
2015/07/30 Javascript
解决JS请求服务器gbk文件乱码的问题
2015/10/16 Javascript
基于jQuery实现美观且实用的倒计时实例代码
2015/12/30 Javascript
javascript事件模型介绍
2016/05/31 Javascript
使用jQuery Rotare实现微信大转盘抽奖功能
2016/06/20 Javascript
通过javascript进行UTF-8编码的实现方法
2016/06/27 Javascript
Spring MVC中Ajax实现二级联动的简单实例
2016/07/06 Javascript
jquery插件ContextMenu设置右键菜单
2017/03/13 Javascript
javascript匿名函数中的'return function()'作用
2018/10/15 Javascript
使用vuex存储用户信息到localStorage的实例
2019/11/11 Javascript
Vue 解决通过this.$refs来获取DOM或者组件报错问题
2020/07/28 Javascript
在Python中处理字符串之isdigit()方法的使用
2015/05/18 Python
Django在Model保存前记录日志实例
2020/05/14 Python
纯HTML5+CSS3制作生日蛋糕代码
2016/11/16 HTML / CSS
农村婚礼证婚词
2014/01/10 职场文书
节约电力资源的建议书
2014/03/12 职场文书
会计电算化专业求职信
2014/06/10 职场文书
机械电子工程专业求职信
2014/06/22 职场文书
党员国庆节演讲稿范文2014
2014/09/21 职场文书
个人先进事迹总结
2015/02/26 职场文书
2019年七夕情人节浪漫祝福语大全!
2019/08/08 职场文书
七年级作文之环保作文
2019/10/17 职场文书
JavaScript实现淘宝商品图切换效果
2021/04/29 Javascript
CentOS7安装GlusterFS集群以及相关配置
2022/04/12 Servers