基于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 中的replace方法说明
Apr 13 Javascript
javascript 模式设计之工厂模式详细说明
May 10 Javascript
javascript通过className来获取元素的简单示例代码
Jan 10 Javascript
js 获取浏览器版本以此来调整CSS的样式
Jun 03 Javascript
node.js中的fs.fstat方法使用说明
Dec 15 Javascript
浅析javascript中的DOM
Mar 01 Javascript
JS获取屏幕高度的简单实现代码
May 24 Javascript
JS中用三种方式实现导航菜单中的二级下拉菜单
Oct 31 Javascript
微信小程序 wx.uploadFile无法上传解决办法
Dec 14 Javascript
微信小程序 生命周期和页面的生命周期详细介绍
Jan 19 Javascript
基于JavaScript实现验证码功能
Apr 01 Javascript
微信小程序文章详情页面实现代码
Sep 10 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
声音就能俘获人心,蕾姆,是哪个漂亮小姐姐配音呢?
2020/03/03 日漫
php 生成短网址原理及代码
2014/01/23 PHP
php cookie名使用点号(句号)会被转换
2014/10/23 PHP
ThinkPHP表单令牌错误的相关解决方法分析
2016/05/20 PHP
JavaScript创建对象的写法
2013/08/29 Javascript
jQuery实现简单二级下拉菜单
2015/04/12 Javascript
javasript实现密码的隐藏与显示
2015/05/08 Javascript
XML文件转化成NSData对象的方法
2015/08/12 Javascript
全面详细的jQuery常见开发技巧手册
2016/02/21 Javascript
js制作支付倒计时页面
2016/10/21 Javascript
json数据处理及数据绑定
2017/01/25 Javascript
js Canvas绘制圆形时钟教程
2017/02/06 Javascript
详解angularJS动态生成的页面中ng-click无效解决办法
2017/06/19 Javascript
vue通过watch对input做字数限定的方法
2017/07/13 Javascript
Angular实现点击按钮后在上方显示输入内容的方法
2017/12/27 Javascript
vue2.0 datepicker使用方法
2018/02/04 Javascript
解决vue项目nginx部署到非根目录下刷新空白的问题
2018/09/27 Javascript
Postman的下载及安装教程详解
2018/10/16 Javascript
JS实现带阴历的日历功能详解
2019/01/24 Javascript
分享一个vue项目“脚手架”项目的实现步骤
2019/05/26 Javascript
[01:42]TI4西雅图DOTA2前线报道 第一顿早饭哦
2014/07/08 DOTA
Python环境搭建之OpenCV的步骤方法
2017/10/20 Python
基于python实现KNN分类算法
2020/04/23 Python
pytorch程序异常后删除占用的显存操作
2020/01/13 Python
Python configparser模块封装及构造配置文件
2020/08/07 Python
英国DIY汽车维修配件网站:DIY Car Service Parts
2019/08/30 全球购物
工商管理专业实习生自我鉴定
2013/09/29 职场文书
大学生个人简历中的自我评价
2013/12/27 职场文书
大学社团活动策划书
2014/01/26 职场文书
会计的岗位职责
2014/03/15 职场文书
高中生班主任评语
2014/04/25 职场文书
社区平安建设汇报材料
2014/08/14 职场文书
部队2015年终工作总结
2015/04/02 职场文书
大学生自我鉴定怎么写
2019/05/07 职场文书
python随机打印成绩排名表
2021/06/23 Python
浅谈Redis跟MySQL的双写问题解决方案
2022/02/24 Redis