vue3中通过自定义指令实现loading加载效果

前言

在现代Web开发中,提升用户体验一直是开发者们追求的目标之一。其中,一个常见的场景就是在用户与应用程序进行交互时,特别是当进行异步操作时(如网络请求),为用户提供即时的反馈,避免用户因为等待而感到困惑或不满。这通常通过显示一个加载指示器(通常称为Loading效果)来实现。本文将深入探讨如何在Vue 3中通过自定义指令的方式来实现Loading加载效果。自定义指令是Vue提供的一种强大工具,允许我们在Vue模板中附加自定义行为。通过自定义指令,我们可以轻松地创建可复用的、可配置的加载效果组件,并将其应用于任何需要显示加载状态的元素上。

演示效果图

image.png

新建index.vue文件

components目录下新建loading目录,并在loading目录下新建index.vue文件

<template><div class="loading-container" v-if="show"><div class="loader"></div><div class="tips">正在快马加鞭的加载中....</div></div>
</template><script setup name="Loading">
const show = ref(false);const showLoading = () => {show.value = true;document.body.style.overflow = "hidden";document.addEventListener("touchmove", () => {}, true);
};
const hideLoading = () => {show.value = false;var mo = function (e) {e.preventDefault();};document.body.style.overflow = "";document.removeEventListener("touchmove", mo, true);
};onMounted(() => {});defineExpose({show,showLoading,hideLoading,
});
</script><style scoped>
.loading-container {position: fixed;top: 0;left: 0;right: 0;bottom: 0;z-index: 9999;background-color: rgba(255, 255, 255, .9);
}
.tips {font-family: "Open Sans";color: #52b852;font-size: 1rem;width: 100%;text-align: center;position: absolute;top: 55%;line-height: 30px;
}
.loader {width: 40px;aspect-ratio: 0.577;clip-path: polygon(0 0, 100% 100%, 0 100%, 100% 0);position: relative;animation: l19 2s infinite linear;overflow: hidden;position: relative;left: 50%;top: 45%;margin: 0 0 0 -25px;
}
.loader:before {content: "";position: absolute;inset: -150% -150%;background: repeating-conic-gradient(from 30deg,#ffabab 0 60deg,#abe4ff 0 120deg,#ff7373 0 180deg);animation: inherit;animation-direction: reverse;
}
@keyframes l19 {100% {transform: rotate(360deg);}
}
</style>
新建loading.js文件

index.vue的同级目录中新建loading.js文件来创建自定义指令

import {createVNode, render, cloneVNode} from "vue"
import Loading from "./index.vue"export default {install(app) {// 使用vue底层的createVNode方法将组件渲染为虚拟节点const VNode = createVNode(Loading)// 使用render函数将组件挂载到body中render(VNode, document.body)// 定义全局方法设置组件的显示和隐藏app.config.globalProperties.$showLoading = VNode.component?.exposed.showLoadingapp.config.globalProperties.$hideLoading = VNode.component?.exposed.hideLoadingconst weakMap = new WeakMap()// 自定义Loading指令app.directive("sy-loading", {mounted(el) {if (weakMap.get(el)) return//  记录当前绑定元素的positionweakMap.set(el, window.getComputedStyle(el).position)},updated(el, binding) {const oldPosition = weakMap.get(el);// 如果不是position: relative或者absolute,就设置为relative// 这里的目的是确保loading组件正确覆盖当前绑定的元素if (oldPosition !== 'absolute' && oldPosition !== 'relative') {el.style.position = 'relative'}// 克隆一份loading元素,// 作用是当页面上有多个zx-loading时,每个dom都维护一份属于自己的loading,不会冲突const newVNode = cloneVNode(VNode)// 挂载当前节点render(newVNode, el)// 判断绑定的值if (binding.value) {newVNode.component?.exposed.showLoading()} else {newVNode.component?.exposed.hideLoading(() => {// 还原布局方式el.style.position = oldPosition})}}})}
}

1. loading.ts

TS写法。上面是js写法,选其中一种即可

import type {App, VNode,} from "vue"
import {createVNode, render, cloneVNode} from "vue"
import Loading from "./index.vue"export default {install(app: App) {// 使用vue底层的createVNode方法将组件渲染为虚拟节点const VNode: VNode = createVNode(Loading )// 使用render函数将组件挂载到body中render(VNode, document.body)// 定义全局方法设置组件的显示和隐藏app.config.globalProperties.$showLoading = VNode.component?.exposed.showLoadingapp.config.globalProperties.$hideLoading = VNode.component?.exposed.hideLoadingconst weakMap = new WeakMap()// 自定义Loading指令app.directive("sy-loading", {mounted(el) {if (weakMap.get(el)) return//  记录当前绑定元素的positionweakMap.set(el, window.getComputedStyle(el).position)},updated(el: HTMLElement, binding: { value: Boolean }) {const oldPosition = weakMap.get(el);// 如果不是position: relative或者absolute,就设置为relative// 这里的目的是确保loading组件正确覆盖当前绑定的元素if (oldPosition !== 'absolute' && oldPosition !== 'relative') {el.style.position = 'relative'}// 克隆一份loading元素,// 作用是当页面上有多个zx-loading时,每个dom都维护一份属于自己的loading,不会冲突const newVNode = cloneVNode(VNode)// 挂载当前节点render(newVNode, el)// 判断绑定的值if (binding.value) {newVNode.component?.exposed.showLoading()} else {newVNode.component?.exposed.hideLoading(() => {// 还原布局方式el.style.position = oldPosition})}}})}
}
main.js引入

main.js中引入loading.js文件。

import Loading from '@/components/loading/Loading.js'
app.use(Loading)
在组件中使用
 v-sy-loading="fullscreenLoading"

在任意组件中的任意标签元素中添加v-sy-loading指定,并设置一个boolean值的参数,即可控制页面的loading加载效果

End

通过本文的介绍,我们详细探讨了如何在Vue 3中利用自定义指令来实现灵活且可复用的Loading加载效果。这一功能不仅优化了用户与应用程序之间的交互体验,还使得加载状态的显示更加直观和易于管理。我们介绍了自定义指令的基本概念、创建过程以及如何在Vue模板中优雅地应用该指令。希望这些内容能帮助你在Vue 3项目中更好地实现Loading加载效果,提升用户体验。未来,随着Vue.js的不断发展和完善,我们期待有更多创新的方法来优化用户界面的交互效果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/697635.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

利用香港多IP服务器进行大数据分析的潜在优势?

利用香港多IP服务器进行大数据分析的潜在优势? 在当今数据驱动的时代&#xff0c;大数据分析已经成为企业获取竞争优势的不二选择。而香港作为一个拥有世界级通信基础设施的城市&#xff0c;提供了理想的环境来部署多IP服务器&#xff0c;从而为大数据分析提供了独特的优势。…

[数据结构1.0]选择排序

鼠鼠前面的博客介绍过选择排序是常见的排序算法&#xff0c;选择排序有但不限于直接选择排序和堆排序&#xff01;那么鼠鼠今天浅谈一下选择排序&#xff01; 鼠鼠本博客用排升序来介绍选择排序&#xff01; 目录 1.直接选择排序 1.1.直接选择排序 1.2.直接选择排序特性 2…

20240513,常用算法(查找,排序,拷贝替换)

做着一些和考试无关的事情 常用查找算法——续 FIND_IF find_if //按条件查找元素&#xff0c;返回迭代器POS / END()find_if(beg,end,_Fred) _Fred函数或谓词&#xff08;返回BOOL类型的仿函数&#xff09; #include<iostream> #include<string> #includ…

Raft论文阅读笔记+翻译:In Search of Understandable Consensus Algorithm

In Search of Understandable Consensus Algorithm 摘要 Raft是一种管理复制日志的共识算法。它产生与&#xff08;多&#xff09;Paxos等效的结果&#xff0c;并且与Paxos一样高效&#xff0c;但其结构与Paxos不同。这使得Raft比Paxos更易理解&#xff0c;也为构建实际系统提供…

​​​【收录 Hello 算法】第 6 章 哈希表

目录 第 6 章 哈希表 本章内容 第 6 章 哈希表 Abstract 在计算机世界中&#xff0c;哈希表如同一位聪慧的图书管理员。 他知道如何计算索书号&#xff0c;从而可以快速找到目标图书。 本章内容 6.1 哈希表6.2 哈希冲突6.3 哈希算法6.4 小结

爱普生推出适用于物联网小尺寸温补晶振TG1612SLN

爱普生推出一款小尺寸温补晶振TG1612SLN&#xff0c;之前推出的小尺寸温补晶振TG2016SLN&#xff0c;封装2016已经是很小了&#xff0c;而TG1612SLN的尺寸仅为1.6x1.2x0.45毫米&#xff0c;不得不佩服爱普生的研发能力。 温度补偿晶体振荡器TG1612SLN使用爱普生开发和制造…

企业级WEB服务Nginx安装

企业级WEB服务Nginx安装 1. Nginx版本和安装方式 Mainline version 主要开发版本,一般为奇数版本号,比如1.19Stable version 当前最新稳定版,一般为偶数版本,如:1.20Legacy versions 旧的稳定版,一般为偶数版本,如:1.18Nginx安装可以使用yum或源码安装,但是推荐使用源码编译安…

Ngnix VTS模块添加和测试

目录 VTS模块介绍 上传软件包xftp/lrzsz 执行脚本 添加vts的配置 测试 测试&#xff1a;nginx.conf配置文件是否有语法错误 测试&#xff1a;windows机器上访问效果 VTS模块介绍 Nginx VTS模块&#xff08;nginx Virtual Host Traffic Status Module&#xff09;是一个第三…

GLU(Gated Linear Unit) 门控线性单元

文章目录 一、RNN二、GLU2.1 整体结构2.2 输入层(Input SentenceLookup Table)2.3 中间层(ConvolutionGate)2.4 输出层(Softmax)2.5 实验结果2.6 实现代码 三、RNN与GLU的对比参考资料 GLU可以理解为能够并行处理时序数据的CNN网络架构&#xff0c;即利用CNN及门控机制实现了RN…

ES扩缩容

ES扩容 1.1 页面扩容ES1 1.2 拷贝插件及ssl文件 JSON [ec_admin@kde-offline3 ~]$ sudo rsync -avP /usr/kde_ec/2.3.6.6-1/elasticsearch1/plugins/* kde-offline6:/usr/kde_ec/2.3.6.6-1/elasticsearch1/plugins/ ;echo $? [ec_admin@kde-offline3 ~]$ sudo rsync -avP /us…

“圣诞树图案的打印~C语言”

圣诞树图案的打印~C语言 题目原文&#xff1a;[圣诞树](https://www.nowcoder.com/practice/9a03096ed8ab449e9b10b0466de29eb2?tpId107&rp1&ru/ta/beginner-programmers&qru/ta/beginner-programmers/question-ranking&difficulty&judgeStatus&tags&…

linux部署安装DataX和DataX-Web

1.基础环境 JDK&#xff08;1.8 及其以上都可以&#xff0c;推荐 1.8&#xff09;&#xff0c;安装过程略 Python&#xff08;2 或者 3 都可以&#xff09;&#xff0c;安装过程略 Apache Maven 3.6.1&#xff08;只有DataX源码编译安装时需要&#xff09; 1.1下载maven安装…