基于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 相关文章推荐
js 获取中文拼音,Select自动匹配字母获取值的代码
Sep 23 Javascript
16个最流行的JavaScript框架[推荐]
May 29 Javascript
js中的eventType事件及其浏览器支持性介绍
Nov 29 Javascript
js实现文本框支持加减运算的方法
Aug 19 Javascript
JS根据生日月份和日期计算星座的简单实现方法
Nov 24 Javascript
Angular中ng-bind和ng-model的区别实例详解
Apr 10 Javascript
Angular中封装fancyBox(图片预览)遇到问题小结
Sep 01 Javascript
js构造函数创建对象是否加new问题
Jan 22 Javascript
20行JS代码实现粘贴板复制功能
Feb 06 Javascript
vue 表单输入格式化中文输入法异常问题
May 30 Javascript
微信小程序实现时间预约功能
Nov 27 Javascript
JavaScript实现简单日历效果
Sep 11 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
数据库相关问题
2006/10/09 PHP
PHP使用php-resque库配合Redis实现MQ消息队列的教程
2016/06/29 PHP
删除PHP数组中的重复元素的实现代码
2017/04/10 PHP
PHP 模拟登陆功能实例详解
2019/09/10 PHP
js实现iframe动态调整高度的代码
2008/01/06 Javascript
javascript 有用的脚本函数
2009/05/07 Javascript
IE下js调试工具Companion.JS
2010/10/15 Javascript
Javascript设置对象的ReadOnly属性(示例代码)
2013/12/25 Javascript
JS来动态的修改url实现对url的增删查改
2014/09/05 Javascript
jQuery实现气球弹出框式的侧边导航菜单效果
2015/09/22 Javascript
深入浅析knockout源码分析之订阅
2016/07/12 Javascript
浅谈js数组和splice的用法
2016/12/04 Javascript
vue component组件使用方法详解
2017/07/14 Javascript
微信小程序仿朋友圈发布动态功能
2018/07/15 Javascript
详解angularjs跨页面传参遇到的一些问题
2018/11/01 Javascript
JavaScript函数的4种调用方法实例分析
2019/03/05 Javascript
vue 开发之路由配置方法详解
2019/12/02 Javascript
[01:20]DOTA2 2017国际邀请赛冠军之路无止竞
2017/06/19 DOTA
Python2.x和3.x下maketrans与translate函数使用上的不同
2015/04/13 Python
将Django项目部署到CentOs服务器中
2018/10/18 Python
pytorch 共享参数的示例
2019/08/17 Python
浅谈Python中的生成器和迭代器
2020/06/19 Python
python删除指定列或多列单个或多个内容实例
2020/06/28 Python
python爬虫beautifulsoup库使用操作教程全解(python爬虫基础入门)
2021/02/19 Python
CSS3按钮鼠标悬浮实现光圈效果源码
2016/09/11 HTML / CSS
乌克兰移动电子产品和相关配件的在线商店:iTMag
2020/03/16 全球购物
口腔工艺技术专业毕业生自荐信
2013/09/27 职场文书
项目施工员岗位职责
2014/03/09 职场文书
销售人员求职的自我评价分享
2014/03/15 职场文书
有趣的广告词
2014/03/18 职场文书
质量提升方案
2014/06/16 职场文书
高三英语复习计划
2015/01/19 职场文书
幼儿园教研工作总结2015
2015/05/12 职场文书
钓鱼岛事件感想
2015/08/11 职场文书
大学生入党自我鉴定范文
2019/06/21 职场文书
青岛市的收音机研制与生产
2022/04/07 无线电