基于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奇异的arguments分析
Oct 20 Javascript
JavaScript显示当然日期和时间即年月日星期和时间
Oct 29 Javascript
分享Javascript中最常用的55个经典小技巧
Nov 29 Javascript
Javascript学习指南
Dec 01 Javascript
jquery图片播放浏览插件prettyPhoto使用详解
Dec 19 Javascript
jquery移动点击的项目到列表最顶端的方法
Jun 24 Javascript
使用bootstrap插件实现模态框效果
May 10 Javascript
微信小程序 Buffer缓冲区的详解
Jul 06 Javascript
通过js控制时间,一秒一秒自己动的实例
Oct 25 Javascript
基于VUE的v-charts的曲线显示功能
Oct 01 Javascript
js实现旋转木马轮播图效果
Jan 10 Javascript
vue-router定义元信息meta操作
Dec 07 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
PHP中cookies使用指南
2007/03/16 PHP
php面向对象全攻略 (十七) 自动加载类
2009/09/30 PHP
PHP中new static()与new self()的区别异同分析
2014/08/22 PHP
php获取json数据所有的节点路径
2015/05/17 PHP
php 文件下载 出现下载文件内容乱码损坏的解决方法(推荐)
2016/11/16 PHP
浅谈PHP中类和对象的相关函数
2017/04/26 PHP
通过Unicode转义序列来加密,按你说的可以算是混淆吧
2007/05/06 Javascript
JavaScript闭包 懂不懂由你反正我是懂了
2011/10/21 Javascript
让人期待的2011年度最佳 jQuery 插件分享
2012/03/16 Javascript
jquery 追加tr和删除tr示例代码
2013/09/12 Javascript
JS对select控件option选项的增删改查示例代码
2013/10/21 Javascript
jquery中ajax函数执行顺序问题之如何设置同步
2014/02/28 Javascript
多个$(document).ready()的执行顺序实例分析
2014/07/26 Javascript
javascript创建cookie、读取cookie
2016/03/31 Javascript
JS模拟简易滚动条效果代码(附demo源码)
2016/04/05 Javascript
jquery实现焦点轮播效果
2017/02/23 Javascript
jQuery实现鼠标滑过预览图片大图效果的方法
2017/04/26 jQuery
解决vue的 v-for 循环中图片加载路径问题
2018/09/03 Javascript
jQuery Raty星级评分插件使用方法实例分析
2019/11/25 jQuery
Python2.x版本中cmp()方法的使用教程
2015/05/14 Python
Python+Socket实现基于TCP协议的客户与服务端中文自动回复聊天功能示例
2017/08/31 Python
Python对Excel按列值筛选并拆分表格到多个文件的代码
2019/11/05 Python
Python调用.NET库的方法步骤
2019/12/27 Python
python使用Thread的setDaemon启动后台线程教程
2020/04/25 Python
Python爬虫设置ip代理过程解析
2020/07/20 Python
全球最大运动品牌的男装、女装和童装官方库存商:A&A Sports
2021/01/17 全球购物
Java基础知识面试题
2014/03/25 面试题
经贸日语毕业生自荐信
2013/11/03 职场文书
毕业生求职自荐信怎么写
2014/01/08 职场文书
初一地理教学反思
2014/01/16 职场文书
网上蛋糕店创业计划书
2014/01/24 职场文书
材料工程专业毕业生求职信
2014/03/04 职场文书
2014年实验室工作总结
2014/12/03 职场文书
2015年政协委员工作总结
2015/05/20 职场文书
会计入职心得体会
2016/01/22 职场文书
Vue2项目中对百度地图的封装使用详解
2022/06/16 Vue.js