记录--Vue自定义指令实现加载中效果v-load(不使用Vue.extend)
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
网站效果演示:ashuai.work:8888/#/myLoad
GitHub仓库地址代码:github.com/shuirongshu…
加载中思路分析
实现加载中效果,一般有两种方式:
- 第一种是:搞一个
load组件,然后使用Vue.extend()方法去继承一个加载组件去使用,比如笔者的这篇文章:juejin.cn/post/702172… - 第二种是:直接使用指令去在需要加载的
dom上去创建一个加载中的dom元素,并指定相应的样式即可。本篇文章说的是第二种。
我们先看一下效果图
v-load效果图
实现步骤一:加上自定义指令
假设我有一个dom元素,我给其加上一个自定义的指令v-load="loading",绑定一个具体的布尔值loading,用于控制开启加载中和关闭加载中
<div class="box" v-load="loading">111</div>
loading: true
.box {
width: 160px;
height: 80px;
border: 2px solid #666;
}
接下来,我就要在自定义指令的相关钩子函数中去操作这个dom元素。
关于自定义指令的入门基础知识可以看官方文档,或者参见笔者之前的关于自定义指令的文章:juejin.cn/post/702960…
实现步骤二:给目标元素创建一个子元素dom用于加载
在自定义指令的初始化bind钩子函数中,我们可以拿到这个dom元素,首先给这个目标元素开始相对定位,让用于加载中的子元素dom去绝对定位,以这个相对定位的父元素进行参考
bind(el, binding) {
const target = el;
// 父元素相对定位
target.style.position = "relative";
// 子元素遮罩层部分
let loadChild = document.createElement("div");
loadChild.className = "loadClass";
}
上述代码中给加载中的子元素loadChild指定一个样式类名loadClass
在这里小伙伴可能有疑问了,这个自定义指令的样式怎么写呢?自定义指令中也没有style标签啊?
是的,自定义指令中不能直接写样式,不过没关系,我们可以先写好一个css样式,然后引入过来使用啊,如下:
// 引入拆分的样式,便于自定义指令中使用
import './index.css' bind(el, binding) {
......
loadChild.className = "loadClass";
}
这样的话,className的样式,可以在引入的同级目录下的./index.css文件中设置了,loadClass样式如下:
.loadClass {
/* 宽高百分百 */
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
/* 默认背景色和颜色 */
background-color: rgba(255, 255, 255, 0.99);
color: #0b6ed0;
/* 透明度过渡使用搭配display:none; */
opacity: 0.8;
transition: all 0.3s;
/* 居中 */
display: flex;
align-items: center;
justify-content: center;
}
注意,加载中效果开启和消失,不用使用vue自带的过渡组件transition,咱们可以使用透明度搭配搭配display:none;去设置
注意,加载中要以父元素为边界去控制,可不能满屏加载哦
然后初始化的时候,看看v-load绑定的值是true还是false,同时加上一个用于隐藏的类名:load-hide。再把这个加载中的dom元素追加到目标父元素身上。
loadChild.classList.add('load-hide') // 添加类名
target.appendChild(loadChild); // 追加加载中子元素
/* 通过透明度实现过渡动画 */
.load-hide {
opacity: 0;
}
这样的话,初始化的加载中就做好了。v-load绑定的值是false的时,就隐藏之
实现步骤三:当组件更新时,去添加或移除这个load-hide类名
componentUpdated(el, binding, vnode, oldVnode) {
let flag = binding.value
let loadChild = el.querySelector('.loadClass')
if (flag) { // v-load绑定的值为true,就移除这个类名,就能看到了
loadChild.style.display = 'flex'
setTimeout(() => {
loadChild.classList.remove('load-hide')
}, 0);
} else { // 绑定的值为false时,再添加这个类名,同时隐藏dom
loadChild.classList.add('load-hide')
setTimeout(() => {
loadChild.style.display = 'none'
}, 360);
}
},
注意上述代码中为啥不直接隐藏,而是使用定时器延长360毫秒再去隐藏,因为笔者设置的加载dom的过渡时间是0.3秒,即要等到透明度过渡完了以后,再隐藏加载中dom,这样看着就自然一些了。
.loadClass { transition: all 0.3s; }
到这里,咱们的v-load自定义指令的加载中效果,就初步完成了。不过功能有点少,自定义加载中我还想,去动态控制:
- 自定义加载图标名
- 自定义加载文字
- 自定义加载文字颜色
- 自定义加载背景色
那这样怎么办呢?
实现步骤四:优化自定义指令,支持传入更多的参数
此时,我的v-load自定义指令,就不用绑定一个布尔值了。可以考虑绑定一个对象啊,通过控制这个对象的具体值,来动态控制加载中的效果。
- 原来自定义指令绑定:
v-load = loading//typeof loading == 'boolean' - 现在自定义指令绑定:
v-load = loading2//typeof loading2 == 'object'
<div class="box" v-load="loading2">222</div> // 如果想要有更多的配置项,就传一个对象,注意要指定字段
loading2: {
value: true,
icon: "el-icon-eleme", // 自定义加载图标名
text: "客官稍等哦...", // 自定义加载文字
color: "red", // 自定义加载文字颜色
bgColor: "#baf", // 自定义加载背景色
}
传参指定相应字段,自定义指令中接参,就要在相关的钩子中去接收并处理这些参数。
如何处理这些参数?
- v-load绑定的值的类型的判断,是布尔值,还是对象,执行不同的操作
- 使用原生js的方式去,创造dom元素、给dom元素指定类名(或添加删除类名)
- 考虑到性能缘故,可以使用文档碎片优化
document.createDocumentFragment() - 最后丢入遮罩层dom内部即可
完整代码
自定义指令样式文件index.css
.loadClass {
/* 宽高百分百 */
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
/* 默认背景色和颜色 */
background-color: rgba(255, 255, 255, 0.99);
color: #0b6ed0;
/* 透明度过渡使用搭配display:none; */
opacity: 0.8;
transition: all 0.3s;
/* 禁止文字选择 */
user-select: none;
display: flex;
align-items: center;
justify-content: center;
}
/* 通过透明度实现过渡动画 */
.load-hide {
opacity: 0;
}
.loadClass>i {
margin-right: 4px;
}
自定义指令的js文件index.js
注意,自定义指令还需要注册一下才能使用哦
// 引入拆分的样式,便于自定义指令中使用
import './index.css'
export default {
// 初始化绑定dom钩子函数
bind(el, binding) {
const target = el;
// 传参类型判断变量控制
let flag;
let isObj;
if (typeof binding.value == 'boolean') {
flag = binding.value
isObj = false
}
if (typeof binding.value == 'object') {
flag = binding.value.value
isObj = true
}
// 有dom元素才去做操作
if (target) {
// 父元素相对定位
target.style.position = "relative";
// 子元素遮罩层部分
let loadChild = document.createElement("div");
loadChild.className = "loadClass"; // 创建文档碎片性能稍微优化一点点
let fragment = document.createDocumentFragment()
// 孙子元素1加载图标部分
let iSun = document.createElement("i");
iSun.className = isObj ? binding.value.icon : "el-icon-loading";
// 孙子元素2文字提示部分
let spanSun = document.createElement("span");
spanSun.innerHTML = isObj ? binding.value.text : '加载中...'
// 使用文档碎片将iSun和spanSun装起来
fragment.appendChild(iSun);
fragment.appendChild(spanSun);
// 将文档碎片丢入子元素遮罩层内
loadChild.appendChild(fragment);
// 样式判断设置
if (isObj) {
loadChild.style.color = binding.value.color
loadChild.style.backgroundColor = binding.value.bgColor
}
// 若为false,就隐藏
if (!flag) {
loadChild.classList.add('load-hide')
loadChild.style.display = 'none'
} // 父元素添加子元素遮罩层使用
target.appendChild(loadChild);
}
},
// dom组件更新操作控制显示和隐藏
componentUpdated(el, binding, vnode, oldVnode) {
let flag = typeof binding.value == 'boolean' ? binding.value : binding.value.value
let loadChild = el.querySelector('.loadClass')
if (flag) {
loadChild.style.display = 'flex'
setTimeout(() => {
loadChild.classList.remove('load-hide')
}, 0);
} else {
loadChild.classList.add('load-hide')
setTimeout(() => {
loadChild.style.display = 'none'
}, 360); }
},
}
使用自定义load指令的地方
<template>
<div>
<h3>指令方式加载中...</h3>
<br />
<button @click="loadFn">点一下</button>
<br />
<br />
<el-table v-load="loading" border :data="tableData" style="width: 80%">
<el-table-column prop="name" label="姓名"></el-table-column>
<el-table-column prop="age" label="年龄"></el-table-column>
<el-table-column prop="home" label="家乡"></el-table-column>
<el-table-column prop="like" label="爱好"></el-table-column>
</el-table>
<br />
<div class="box" v-load="loading">111</div>
<br />
<div class="box" v-load="loading2">222</div>
</div>
</template> <script>
export default {
name: "myLoadName",
data() {
return {
// 自定义指令方式,默认绑定的值是布尔值
loading: true,
// 如果想要有更多的配置项,就传一个对象,注意要指定字段
loading2: {
value: true,
icon: "el-icon-eleme", // 自定义加载图标名
text: "客官稍等哦...", // 自定义加载文字
color: "red", // 自定义加载文字颜色
bgColor: "#baf", // 自定义加载背景色
},
tableData: [
{
name: "孙悟空",
age: 500,
home: "花果山水帘洞",
like: "桃子",
},
{
name: "猪八戒",
age: 88,
home: "高老庄",
like: "肉包子",
},
{
name: "沙和尚",
age: 1000,
home: "通天河",
like: "游泳",
},
],
};
},
methods: {
loadFn() {
this.loading = !this.loading;
this.loading2.value = !this.loading2.value;
},
},
};
</script> <style lang='less' scoped>
.box {
width: 160px;
height: 80px;
border: 2px solid #666;
box-sizing: border-box;
}
</style>
本文转载于:
https://juejin.cn/post/7182375025368891429
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

记录--Vue自定义指令实现加载中效果v-load(不使用Vue.extend)的更多相关文章
- Android 三种方式实现自定义圆形页面加载中效果的进度条
转载:http://www.eoeandroid.com/forum.php?mod=viewthread&tid=76872 一.通过动画实现 定义res/anim/loading.xml如 ...
- WPF防止界面卡死并显示加载中效果
原文:WPF防止界面卡死并显示加载中效果 网上貌似没有完整的WPF正在加载的例子,所以自己写了一个,希望能帮到有需要的同学 前台: <Window x:Class="WpfApplic ...
- 使用Bootstrap3和Ladda UI实现的多种按钮“加载中”效果体验
在线演示 在线演示 大家在开发基于web的网站或者web应用中,常常在AJAX调用的过程中需要提示用户并且展示相关的“加载中”效果,类似的UI设计也非常多,比如,当点击一个按钮后,在它的旁边显示一个 ...
- Vue 自定义图片懒加载指令v-lazyload
Vue是可以自定义指令的,最近学习过程中遇见了一个需要图片懒加载的功能,最后参考了别人的代码和思路自己重新写了一遍.以下将详细介绍如何实现自定义指令v-lazyload. 先看如何使用这个指令: &l ...
- jQuery实现加载中效果,防止重复提交
//导出表格加载中的提示var dian=0;//控制'●'的个数var t=null;//停止时使用function id_loadspot(loadspotSpan,loadingDiv,expo ...
- jquery mobile在页面加载时添加加载中效果 document.ready 和window.onload执行顺序比较
想要添加这个效果,先来弄明白页面的加载和事件执行顺序,看这个简单例子: <html xmlns="http://www.w3.org/1999/xhtml"> < ...
- 【转】WPF防止界面卡死并显示加载中效果
原文地址:http://www.cnblogs.com/linyijia/archive/2013/02/06/2900609.html <Window x:Class="Loadin ...
- CSS3实现加载中效果
代码: <!doctype html> <html> <head> <meta charset="utf-8" /> <tit ...
- loading加载中效果
(function(){ try{ var ui={ loading:{ addCssStyle:function(text) { var head = document.getElementsByT ...
- 自定义ProgressBar的加载效果
三种方式实现自定义圆形页面加载中效果的进度条 To get a ProgressBar in the default theme that is to be used on white/light b ...
随机推荐
- NC25005 [USACO 2008 Ope S]Clear And Present Danger
题目链接 题目 题目描述 Farmer John is on a boat seeking fabled treasure on one of the N (1 <= N <= 100) ...
- NC207751 牛牛的旅游纪念品
题目链接 题目 题目描述 牛牛在牛市的旅游纪念商店里面挑花了眼,于是简单粗暴的牛牛决定--买最受欢迎的就好了. 但是牛牛的背包有限,他只能在商店的n个物品里面带m个回去,不然就装不下了. 并且牛牛希望 ...
- Linux查看系统版本的方法
记录几种查看当前Linux系统的版本的方法 一.使用命令:cat /proc/version 查看 linux版本号:Linux version 5.4.0-99-generic (buildd@lg ...
- 类型判断,代码块,流程控制及循环---day05
1.类型判断isinstance 用来做判断类型 语法: 用法一: isinstance(要判断的值,要判断的类型) 返回的是真或者假 用法二: isinstance(要判断的值,(可能的类型))如果 ...
- itertools.chain.from_iterable()将嵌套列表合并成一个
from itertools import chain a = [[1,2],[3,4]] print(chain.from_iterable(a)) # [1,2,3,4]
- Flask AttributeError 'Request' object has no attribute 'is_xhr'解决办法
flask版本0.12.5 运行时会报以上错误,原因是因为werkzeug的版本大于等于1.x版本. 解决办法,降低werkzeug的版本即可 pip uninstall Werkzeug pip i ...
- 2024-02-28:用go语言,有一个由x轴和y轴组成的坐标系, “y下“和“y上“表示一条无限延伸的道路,“y下“表示这个道路的下限,“y上“表示这个道路的上限, 给定一批长方形,每一个长方形有(
2024-02-28:用go语言,有一个由x轴和y轴组成的坐标系, "y下"和"y上"表示一条无限延伸的道路,"y下"表示这个道路的下限,& ...
- npm模块全局安装后无法使用解决方案
好家伙 npm模块全局安装后无法使用 估计是少配了环境变量 1.使用命令: npm config get prefix 找到全局包的安装位置 2.随后我们右键"我的电脑"打 ...
- HAProxy端口资源耗尽的解决办法
项目背景 系统使用HAProxy为mq和部分应用的负载均衡服务.近期,瞬时流量过大,导致出现连锁反应,HA开始波动. HAProxy版本:1.6.3 问题分析 心跳检测大量失败,项目状态极不稳定.观察 ...
- CT图像重建
20世纪70年代中期,在医学领域出现了一种神奇装置,名为"计算机辅助 X 射线断层成像仪"(简称CAT或CT),它能够在不损伤病人的情况下,提供人体从头到脚各部位的断层X射线图像. ...
