这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

网站效果演示: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)的更多相关文章

  1. Android 三种方式实现自定义圆形页面加载中效果的进度条

    转载:http://www.eoeandroid.com/forum.php?mod=viewthread&tid=76872 一.通过动画实现 定义res/anim/loading.xml如 ...

  2. WPF防止界面卡死并显示加载中效果

    原文:WPF防止界面卡死并显示加载中效果 网上貌似没有完整的WPF正在加载的例子,所以自己写了一个,希望能帮到有需要的同学 前台: <Window x:Class="WpfApplic ...

  3. 使用Bootstrap3和Ladda UI实现的多种按钮“加载中”效果体验

    在线演示 在线演示 大家在开发基于web的网站或者web应用中,常常在AJAX调用的过程中需要提示用户并且展示相关的“加载中”效果,类似的UI设计也非常多,比如,当点击一个按钮后,在它的旁边显示一个 ...

  4. Vue 自定义图片懒加载指令v-lazyload

    Vue是可以自定义指令的,最近学习过程中遇见了一个需要图片懒加载的功能,最后参考了别人的代码和思路自己重新写了一遍.以下将详细介绍如何实现自定义指令v-lazyload. 先看如何使用这个指令: &l ...

  5. jQuery实现加载中效果,防止重复提交

    //导出表格加载中的提示var dian=0;//控制'●'的个数var t=null;//停止时使用function id_loadspot(loadspotSpan,loadingDiv,expo ...

  6. jquery mobile在页面加载时添加加载中效果 document.ready 和window.onload执行顺序比较

    想要添加这个效果,先来弄明白页面的加载和事件执行顺序,看这个简单例子: <html xmlns="http://www.w3.org/1999/xhtml"> < ...

  7. 【转】WPF防止界面卡死并显示加载中效果

    原文地址:http://www.cnblogs.com/linyijia/archive/2013/02/06/2900609.html <Window x:Class="Loadin ...

  8. CSS3实现加载中效果

    代码: <!doctype html> <html> <head> <meta charset="utf-8" /> <tit ...

  9. loading加载中效果

    (function(){ try{ var ui={ loading:{ addCssStyle:function(text) { var head = document.getElementsByT ...

  10. 自定义ProgressBar的加载效果

    三种方式实现自定义圆形页面加载中效果的进度条 To get a ProgressBar in the default theme that is to be used on white/light b ...

随机推荐

  1. 文心一言 VS 讯飞星火 VS chatgpt (198)-- 算法导论14.3 6题

    六.用go语言,说明如何来维护一个支持操作MIN-GAP的一些数的动态集Q,使得该操作能给出Q中两个最接近的数之间的差值.例如,Q=(1,5,9,15,18,22),则MIN-GAP返回18-15=3 ...

  2. 使用yum查询系统安装的软件及可以更新的软件并单独指定升级某一个软件

    Linux系统下yum命令查看安装了哪些软件包: $yum list installed //列出所有已安装的软件包 yum针对软件包操作常用命令: 1.使用YUM查找软件包 命令:yum searc ...

  3. 解决邮件客户端QQ Mail及Thunderbird无法登入Outlook的问题

    最近无论是安卓手机的邮件客户端, 或者是 Ubuntu 下的 Thunderbird 都无法登入 Outlook 账号, 原因是需要开启双因素验证. 这个在 Outlook 界面上是不能直接设置的, ...

  4. 使用 Oracle PL/SQL NOCOPY 提示

    参考文献:       official document: http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/tuning.htm#LNPL ...

  5. bootstrap与javascript

    1.bootstrap依赖 bootstrap依赖javascript类库,jQuery 下载jQuery,在页面上应用jQuery 在页面上应用bootstrap的js类库 <script s ...

  6. postgresql中的json和jsonb

    1. 简介postgresql9.3以后,我们可以将表的字段类型设置为json.同时,postgresql还提供了jsonb格式,jsonb是json的二进制形式.二者区别: postgresql9. ...

  7. python字符串模板文本处理之Template

    from string import Template s = Template('$who 在 $do') ts = s.substitute(who="张三", do=&quo ...

  8. You can't specify target table for update in FROM clause

    mysql中You can't specify target table for update in FROM clause错误的意思是说,不能先select出同一表中的某些值,再update这个表( ...

  9. 【Azure Function App】Java Function部署到Azure后出现中文显示乱码问题

    问题描述 Java Function在Azure上遇见中文显示乱码问题?如何解决呢? 问题解答 中文字符显示为乱码,这个情况就是服务实例上设置的编码格式不是统一的UTF-8所导致的. 在查看Azure ...

  10. 图数据库认证考试 NGCP 错题解析 vol.02:这 10 道题竟无一人全部答对

    如果你读过「NebulaGraph 错题解析第一期」,大概知道在错题解析未出来之前,NebulaGraph 专业技能认证 NGCP(全称 NebulaGraph Certified Professio ...