基于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 相关文章推荐
Firefox 无法获取cssRules 的解决办法
Oct 11 Javascript
获取客户端网卡MAC地址和IP地址实现JS代码
Mar 17 Javascript
JavaScript中的ArrayBuffer详细介绍
Dec 08 Javascript
jQuery实现瀑布流布局
Dec 12 Javascript
JQuery基础语法小结
Feb 27 Javascript
Jquery代码实现图片轮播效果(一)
Aug 12 Javascript
JavaScript中将数组进行合并的基本方法讲解
Mar 07 Javascript
js基于myFocus实现轮播图效果
Feb 14 Javascript
js数组去重的N种方法(小结)
Jun 07 Javascript
Vue中UI组件库之Vuex与虚拟服务器初识
May 07 Javascript
webpack DllPlugin xxx is not defined解决办法
Dec 13 Javascript
vue实现广告栏上下滚动效果
Nov 26 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
检查url链接是否已经有参数的php代码 添加 ? 或 &amp;
2010/02/09 PHP
php下过滤html代码的函数 提高程序安全性
2010/03/02 PHP
一步一步学习PHP(8) php 数组
2010/03/05 PHP
php用户注册页面利用js进行表单验证具体实例
2013/10/17 PHP
php动态函数调用方法
2015/05/21 PHP
php目录拷贝实现方法
2015/07/10 PHP
tp5.1框架数据库子查询操作实例分析
2020/05/26 PHP
判断是否输入完毕再激活提交按钮
2006/06/26 Javascript
JS的事件绑定深入认识
2014/06/26 Javascript
jQuery+ajax实现鼠标单击修改内容的方法
2014/06/27 Javascript
JavaScript获取页面中第一个锚定文本的方法
2015/04/03 Javascript
JavaScript 最佳实践:帮你提升代码质量
2016/12/03 Javascript
jQuery简单实现的HTML页面文本框模糊匹配查询功能完整示例
2018/05/09 jQuery
微信小程序生成海报分享朋友圈的实现方法
2019/05/06 Javascript
js计算两个时间差 天 时 分 秒 毫秒的代码
2019/05/21 Javascript
Vue分页器实现原理详解
2019/06/28 Javascript
微信小程序实现下拉框功能
2019/07/16 Javascript
解决vant title-active-color与title-inactive-color不生效问题
2020/11/03 Javascript
Angular处理未可知异常错误的方法详解
2021/01/17 Javascript
[02:40]DOTA2英雄基础教程 炼金术士
2013/12/23 DOTA
举例讲解Python程序与系统shell交互的方式
2015/04/09 Python
使用Python写个小监控
2016/01/27 Python
python 处理微信对账单数据的实例代码
2019/07/19 Python
python3操作注册表的方法(Url protocol)
2020/02/05 Python
使用npy转image图像并保存的实例
2020/07/01 Python
营销与策划应届生求职信
2013/11/04 职场文书
喜之郎果冻广告词
2014/03/20 职场文书
乡镇信息公开实施方案
2014/03/23 职场文书
家长对老师的评语
2014/04/18 职场文书
文明寝室申报材料
2014/05/12 职场文书
解除聘用合同证明书范本
2014/09/11 职场文书
党的群众路线教育实践活动制度建设计划方案
2014/10/31 职场文书
医院岗前培训心得体会
2016/01/08 职场文书
2019暑期安全倡议书!
2019/06/27 职场文书
Jackson 反序列化时实现大小写不敏感设置
2021/06/29 Java/Android
小程序实现悬浮按钮的全过程记录
2021/10/16 HTML / CSS