【学习记录24】vue3自定义指令

一、在单vue文件中直接使用

1、html部分

<template><divstyle="height: 100%;"v-loading="loading"><ul><li v-for="item in data">{{item}} - {{item * 2}}</li></ul></div>
</template>

 2、js部分

<script setup>import {ref} from 'vue'// loading图片路径import imgSrc from '@/views/loading.gif'const data = ref(1)// 定义loading初始值为true,插入loadingconst loading = ref(true)// 单页面自定义指令直接使用v开头驼峰命名变量,如下const vLoading = {// dom加载完,在使用v-loading指令的html节点里添加dommounted (el, binding) {const div =  document.createElement('div')div.className = 'loading'const img = document.createElement('img')img.src = imgSrcimg.width = 40div.appendChild(img)el.appendChild(div)},updated(el, binding) {// 当值loading绑定的值为false的时候删除domif (!binding.value) {const loadingDom = document.querySelector('.loading')el.removeChild(loadingDom)}}}// 模拟异步数据,2秒后loading值为falsesetTimeout(() => {loading.value = falsedata.value = 50}, 2000)
</script>

3、实现效果

二、全局注册使用

1、html部分

<template><divstyle="height: 100%;"v-loading="loading"><ul><li v-for="item in data">{{item}} - {{item * 2}}</li></ul></div>
</template>

2、js部分

在components下创建loading文件夹,在loading文件夹里创建directive.js 

// direcitve.jsimport imgSrc from "@/views/loading.gif";const loadingDirective = {mounted(el, binding) {const div = document.createElement('div')div.className = 'loading'const img = document.createElement('img')img.src = imgSrcimg.width = 40div.appendChild(img)el.appendChild(div)},updated(el, binding) {if (!binding.value) {const loadingDom = document.querySelector('.loading')el.removeChild(loadingDom)}}
}
export default loadingDirective

在main.js中全局注册指令

// 引入loading
import loadingDirective from './components/loading/directive'let app = createApp(App)app.use(ElementPlus).use(router)
app.directive('loading', loadingDirective) // 全局注册
app.mount('#app')

三、使用vue组件文件实现自定义指令

1、在components下创建loading文件夹,在loading文件夹里创建directive.js

2、在loading文件夹里创建loading.vue

3、在loading文件夹里放入一张GIF图(loading.gif)

 

 1、loading.vue文件源码

// loading.vue<template><div class="loading"><div class="loading-content"><img src="./loading.gif" width="24" height="24" alt=""><p class="desc">{{title}}</p></div></div>
</template><script setup>// vue3 写法import { ref, defineExpose } from 'vue'const title = ref('正在加载...')const setTitle = (t) => {title.value = t}// 导出setTitle方法defineExpose({setTitle})// vue2 写法// export default {//   name: 'loading',//   data() {//     return {//       title: '正在加载...'//     }//   },//   methods: {//     setTitle(title) {//       this.title = title//     }//   }// }
</script><style scoped lang="scss">.loading {position: absolute;top: 50%;left: 50%;transform: translate3d(-50%, -50%, 0);.loading-content {text-align: center;.desc {line-height: 20px;font-size: $font-size-small;color: $color-text-l;}}}
</style>

2、js部分(directive.js) 

// directive.js// 引入vue方法createApp
import {createApp} from 'vue'
// 引入添加dom和删除dom的方法
import {addClass, removeClass} from '@/assets/js/dom'const relativeCls = 'g-relative'
const loadingDirective = {mounted (el, binding) {// 创建一个loading的vue实例const app = createApp(Loading)// 挂载loading.vue 到div DOM上const instance = app.mount(document.createElement('div'))// 把instance挂到要用指令的element下el.instance = instanceconst title = binding.arg// 如果传了title就重新设置title的值if (typeof title !== 'undefined') {instance.setTitle(title)}// 指令绑定的值为true把自定义的vue实例下的dom节点$el添加到el下if (binding.value) {append(el)}},// 指令绑定的值更新以后updated (el, binding) {const title = binding.argif (typeof title !== 'undefined') {el.instance.setTitle(title)}if (binding.value !== binding.oldValue) {// 指令绑定的值为true添加指令dom,否则删除指令的dombinding.value ? append(el) : remove(el)}}
}function append(el) {const style = getComputedStyle(el)// 如果要绑定的dom没有定位就添加一个有定位的classiif (!['absolute', 'fixed', 'relative'].includes(style.position)) {addClass(el, relativeCls)}el.appendChild(el.instance.$el)
}function remove(el) {removeClass(el, relativeCls)el.removeChild(el.instance.$el)
}export default loadingDirective

 3、@/assets/js/dom.js源码

export function addClass(el, className) {if (!el.classList.contains(className)) {el.classList.add(className)}
}export function removeClass(el, className) {el.classList.remove(className)
}

4、main.js源码 

// 引入loading
import loadingDirective from './components/loading/directive'let app = createApp(App)app.use(ElementPlus).use(router)
app.directive('loading', loadingDirective) // 全局注册
app.mount('#app')

四、进阶(有多个自定义指令)

1、封装一个通用的js

把自定义组件的方法拎出来单独弄一个js文件,我习惯放在src/assets/js/create-my-like-directive.js

// create-my-like-directive.jsimport { createApp } from 'vue'
import { addClass, removeClass } from '@/assets/js/dom'const relativeCls = 'g-relative'export default function createMyLikeDirective (Comp) { // 改动的地方,变成可传参的方法return {mounted (el, binding) {const app = createApp(Comp)  // 传入变动参数const instance = app.mount(document.createElement('div'))const name = Comp.nameif (!el[name]) {el[name] = {}}// 把实例挂载到dom的name下,防止多个自定义指令互相影响干扰出现bugel[name].instance = instanceconst title = binding.argif (title) {instance.setTitle(title)}if (binding.value) {append(el)}},updated (el, binding) {const title = binding.argconst name = Comp.nameif (title) {el[name].instance.setTitle(title)}if (binding.value !== binding.oldValue) {binding.value ? append(el) : remove(el)}}}function append (el) {const style = getComputedStyle(el)const name = Comp.nameif (!['absolute', 'fixed', 'relative'].includes(style.position)) {addClass(el, relativeCls)}el.appendChild(el[name].instance.$el)}function remove (el) {const name = Comp.nameremoveClass(el, relativeCls)el.removeChild(el[name].instance.$el)}
}

2、directive.js修改

import Loading from './loading.vue'
import createMyLikeDirective from '@/assets/js/create-my-like-directive'
// 如果有不同的自定义好的vue文件,Loading变为别的vue文件即可
const loadingDirective = createMyLikeDirective(Loading)export default loadingDirective

 3、main.js修改

// 引入loading
import loadingDirective from './components/loading/directive'// 引入其他的
import AAAA from './components/AAAA/directive'
import BBBB from './components/BBBB/directive'let app = createApp(App)app.use(ElementPlus).use(router)
app.directive('loading', loadingDirective) // 全局注册
app.directive('aaaa', AAAA) // 全局注册
app.directive('bbbb', BBBB) // 全局注册
app.mount('#app')

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

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

相关文章

基于YOLOv8深度学习的智能肺炎诊断系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

CentOS stream 9配置网卡

CentOS stream9的网卡和centos 7的配置路径&#xff1a;/etc/sysconfig/network-scripts/ifcfg-ens32不一样。 CentOS stream 9的网卡路径&#xff1a; /etc/NetworkManager/system-connections/ens32.nmconnection 方法一&#xff1a; [connection] idens32 uuid426b60a4-4…

2024 CKA 题库 | 11、创建 PVC

不等更新题库 文章目录 11、创建 PVC题目:考点&#xff1a;参考链接:解答:更换 context创建 pvc创建 pod修改 pvc 并记录 11、创建 PVC 题目: 设置配置环境&#xff1a; [candidatenode-1] $ kubectl config use-context ok8sTask 创建一个新的 PersistentVolumeClaim&#x…

SG-9101CGA(汽车+125°C可编程晶体振荡器)

SG-9101CGA是用于汽车CMOS输出的可编程晶体振荡器&#xff0c;彩用2.5 x 2.0 (mm)封装&#xff0c;0.67 MHz至170 MHz频率范围、工作温度范围为-40℃~125℃&#xff0c;符合车规级晶振&#xff0c;无铅&#xff0c;绿色环保&#xff0c;满足汽车工业标准&#xff0c;电源电压范…

【linux】粘滞位.yum

粘滞位 1.为什么我们普通用户可以删掉别人的文件&#xff08;包括root&#xff09;?合理吗&#xff1f; 2.删除一个文件和目标文件有关系吗&#xff1f; 没关系&#xff0c;和所处的目录有关系。 1.我们先以root身份创建一个目录&#xff0c;接着在这个目录下创建一个文件 2…

噪声的产生机制和来源

噪声广泛存&#xff0c;噪声按照噪声携带能量的强弱分为功率型噪声和信号型噪声&#xff0c;功率型噪声持续时间短&#xff0c;能量强&#xff0c;对设备的寿命具有很大的影响&#xff0c;而信号型噪声顾名思义来源于信号且作用于信号&#xff0c;本节简述噪声的产生机理和来源…

QtAV:基于Qt和FFmpeg的跨平台高性能音视频播放框架

目录 一.简介 1.特性 2.支持的平台 3.简单易用的接口 二.编译 1.下载依赖包 2.开始编译 2.1克隆 2.2修改配置文件 2.3编译 三.试用 一.简介 官网地址&#xff1a;http://www.qtav.org/ Github地址&#xff1a;https://github.com/wang-bin/QtAV 1.特性 ●支持大部分…

Windows 开启卓越性能模式

在powershell命令行中输入下面代码即可&#xff1a; powercfg -duplicatescheme e9a42b02-d5df-448d-aa00-03f14749eb61

机器学习--人工智能概述

人工智能概述 入门人工智能&#xff0c;了解人工智能是什么。为啥发展起来&#xff0c;用途是什么&#xff0c;是最重要也是最关键的事情。大致有以下思路。 人工智能发展历程机器学习定义以及应用场景监督学习&#xff0c;无监督学习监督学习中的分类、回归特点知道机器学习…

Producer源码解读

Producer源码解读 在 Kafka 中, 我们把产生消息的一方称为 Producer 即 生产者, 它是 Kafka 的核心组件之一, 也是消息的来源所在。它的主要功能是将客户端的请求打包封装发送到 kafka 集群的某个 Topic 的某个分区上。那么这些生产者产生的消息是怎么传到 Kafka 服务端的呢&a…

TypeScript依赖注入框架Typedi的使用、原理、源码解读

简介 typedi是一个基于TS的装饰器和reflect-metadata的依赖注入轻量级框架&#xff0c;使用简单易懂&#xff0c;方便拓展。 使用typedi的前提是安装reflect-metadata&#xff0c;并在项目的入口文件的第一行中声明import ‘reflect-metadata’&#xff0c;这样就会在原生的R…

【图解数据结构】深度解析时间复杂度与空间复杂度的典型问题

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;图解数据结构、算法模板 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 一. ⛳️上期回顾二. ⛳️常见时间复杂度计算举例1️⃣实例一2️⃣实例二3️⃣实例三4️⃣实例四5…

FPGA引脚选择(Select IO)--认知1

主要考虑功能角度&#xff08;速度&#xff0c;电平匹配&#xff0c;内部程序编写&#xff09;去找研究芯片内部资源 1. 关键字 HP I/O Banks, High performance The HP I/O banks are deisgned to meet the performance requirements of high-speed memory and other chip-to-…

参照oracle按名称排序,用js在前端对附件封装排序方法

此前因客户需求需要附件按照名称排序 而后台无法对单个文件夹做单独处理。虽可以在每次点击之后重新调用接口&#xff0c;再组装数据&#xff0c;但效率太低&#xff0c;且无须存储&#xff0c;而存储在当前文件夹的排序方法也需要更新。索性自己写了一个通用的方法。经测试排序…

彩超框架EchoSight开发日志记录

EchoSight开发记录 蒋志强 我会不定期的更新 开发进展。最近更新进展于2024年1月15日 1.背景 由于某些不可抗逆的原因&#xff0c;离开了以前的彩超大厂&#xff0c;竞业在家&#xff0c;难得有空闲的时间。我计划利用这段时间 自己独立 从零开始 搭建一套 彩超系统的软件工…

【陈老板赠书活动 - 22期】- 人工智能(第三版)

陈老老老板&#x1f9d9;‍♂️ &#x1f46e;‍♂️本文专栏&#xff1a;赠书活动专栏&#xff08;为大家争取的福利&#xff0c;免费送书&#xff09; &#x1f934;本文简述&#xff1a;活就像海洋,只有意志坚强的人,才能到达彼岸。 &#x1f473;‍♂️上一篇文章&#xff…

浅谈CPU进入保护模式的方法

看程序要想思路不乱&#xff0c;最重要的就是要抓到程序的主线&#xff0c;不要被一些只是用来保护的代码打乱。如何抓到主线呢&#xff1f;比较法学习代码是比较有效的&#xff0c;比如对于CPU如何进入保护模式的理解。 不同的操作系统作者有自己的方法&#xff0c;代码看起来…

高级编程JavaScript中的数据类型?存储上能有什么差别?

在JavaScript中&#xff0c;我们可以分成两种类型&#xff1a; 基本类型复杂类型 两种类型的区别是&#xff1a;存储位置不同 一、基本类型 基本类型主要为以下6种&#xff1a; NumberStringBooleanUndefinednullsymbol Number 数值最常见的整数类型格式则为十进制&…

Liunx:线程控制

目录 创建线程&#xff1a;pthread_create(); 线程等待&#xff1a;pthread_join(); 线程退出&#xff1a;pthread_exit(); 线程取消&#xff1a;pthread_cancel() 说线程的时候说过&#xff0c;liunx没有选择单独定义线程的数据结构和适配算法&#xff0c;而是用轻量级进程…

【计算机网络】OSI七层模型与TCP/IP四层模型的对应与各层介绍

1 OSI七层模型与TCP/IP四层模型对应 2 OSI七层模型介绍 OSI&#xff08;Open Systems Interconnection&#xff09;模型是一个由国际标准化组织&#xff08;ISO&#xff09;定义的七层网络体系结构&#xff0c;用于描述计算机网络中的通信协议。每一层都有特定的功能&#xff…