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

news2024/9/28 23:27:44

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

1、html部分

<template>
  <div
    style="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,插入loading
  const loading = ref(true)

  // 单页面自定义指令直接使用v开头驼峰命名变量,如下
  const vLoading = {
    // dom加载完,在使用v-loading指令的html节点里添加dom
    mounted (el, binding) {
      const div =  document.createElement('div')
      div.className = 'loading'
      const img = document.createElement('img')
      img.src = imgSrc
      img.width = 40
      div.appendChild(img)
      el.appendChild(div)
    },
    updated(el, binding) {
      // 当值loading绑定的值为false的时候删除dom
      if (!binding.value) {
        const loadingDom = document.querySelector('.loading')
        el.removeChild(loadingDom)
      }
    }
  }

  // 模拟异步数据,2秒后loading值为false
  setTimeout(() => {
    loading.value = false
    data.value = 50
  }, 2000)
</script>

3、实现效果

二、全局注册使用

1、html部分

<template>
  <div
    style="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.js

import 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 = imgSrc
    img.width = 40
    div.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 = instance
    const 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.arg
    if (typeof title !== 'undefined') {
      el.instance.setTitle(title)
    }
    if (binding.value !== binding.oldValue) {
      // 指令绑定的值为true添加指令dom,否则删除指令的dom
      binding.value ? append(el) : remove(el)
    }
  }
}

function append(el) {
  const style = getComputedStyle(el)
  // 如果要绑定的dom没有定位就添加一个有定位的classi
  if (!['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.js

import { 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.name
      if (!el[name]) {
        el[name] = {}
      }
      // 把实例挂载到dom的name下,防止多个自定义指令互相影响干扰出现bug
      el[name].instance = instance
      const title = binding.arg
      if (title) {
        instance.setTitle(title)
      }

      if (binding.value) {
        append(el)
      }
    },
    updated (el, binding) {
      const title = binding.arg
      const name = Comp.name
      if (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.name
    if (!['absolute', 'fixed', 'relative'].includes(style.position)) {
      addClass(el, relativeCls)
    }
    el.appendChild(el[name].instance.$el)
  }

  function remove (el) {
    const name = Comp.name
    removeClass(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.coloradmin.cn/o/1396367.html

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

相关文章

golang面试题大全

go基础类 1、与其他语言相比&#xff0c;使用 Go 有什么好处&#xff1f; 与其他作为学术实验开始的语言不同&#xff0c; Go 代码的设计是务实的。每个功能和语法决策都旨在让程序员的生活更轻松。Golang 针对并发进行了优化&#xff0c;并且在规模上运行良好。由于单一的标…

Java进阶-Tomcat发布JavaWeb项目

对于云服务器&#xff0c;程序员一般不会陌生&#xff0c;如果项目需要发布到现网&#xff0c;那么服务器是必不可缺的一项硬性条件&#xff0c;那么如何在云服务器上部署一个项目&#xff0c;需要做哪些配置准备&#xff0c;下面就由本文档为大家讲解&#xff0c;本篇以Tomcat…

springcloud之链路追踪

写在前面 源码 。 本文一起来看下链路追踪的功能&#xff0c;链路追踪是一种找出病因的手段&#xff0c;可以类比医院的检查仪器&#xff0c;服务医生治病救人&#xff0c;而链路追踪技术是辅助开发人员查找线上问题的。 1&#xff1a;为什么微服务需要链路追踪 孔子同志月过…

python数字图像处理基础(十)——背景建模

目录 背景建模背景消除-帧差法混合高斯模型 背景建模 背景建模是计算机视觉和图像处理中的一项关键技术&#xff0c;用于提取视频中的前景对象。在视频监控、运动检测和行为分析等领域中&#xff0c;背景建模被广泛应用。其基本思想是通过对视频序列中的像素进行建模&#xff…

【信号与系统】【北京航空航天大学】实验四、幅频、相频响应和傅里叶变换

一、实验目的 1、 掌握利用MATLAB计算系统幅频、相频响应的方法&#xff1b; 2、 掌握使用MATLAB进行傅里叶变换的方法&#xff1b; 3、 掌握使用MATLAB验证傅里叶变换的性质的方法。 二、实验内容 1、 MATLAB代码&#xff1a; >> clear all; >> a [1 3 2]; …

干掉xshell, 这款远程终端工具:开源、免费、跨平台,同时支持SSH+SFTP+Telent+TCP+Serial,太香了。

干掉xshell说say you, 这款远程终端工具&#xff1a;开源、免费、跨平台&#xff0c;同时支持SSHSFTPTelentTCPSerial&#xff0c;太香了。 大家好&#xff01; 我是老码农。 今天分享一款&#xff1a;远程终端连接工具&#xff1a;WindTerm。 如标题所述&#xff0c;值得拥…

按空格键改变text显示的内容并打印输出

注意&#xff01;如果焦点不在text则无法生效。 整型竟然能和字符串直接相加&#xff0c;立天&#xff01; import QtQuickWindow {width: 640height: 480visible: truetitle: qsTr("2.2 属性")Rectangle {Text {id: thislabelfont.pixelSize: 30font.family: "…

Elastic Stack(1):Elastic Stack简介

1 简介 ELK是一个免费开源的日志分析架构技术栈总称&#xff0c;官网https://www.elastic.co/cn。包含三大基础组件&#xff0c;分别是Elasticsearch、Logstash、Kibana。但实际上ELK不仅仅适用于日志分析&#xff0c;它还可以支持其它任何数据搜索、分析和收集的场景&#xf…

线程基础知识点

1. 线程和进程的区别&#xff1f; 程序由指令和数据组成&#xff0c;但这些指令要运行&#xff0c;数据要读写&#xff0c;就必须将指令加载至 CPU&#xff0c;数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 IO 的。 当…

自动驾驶概述

自动驾驶技术主要解决的问题 无人驾驶分级 L1:巡航定速(ACC),巡航装置可以纵向控制车辆,可以加速减速 L2:车道保持辅助,系统可以纵向控制也可以横向控制汽车,但车是辅助,人才是主导。 L2.5:可以提供简单路况下的变道能力,比如特斯拉。 L3:L2的基础上提供变道能力,…

[C语言]编译和链接

一、翻译和运行 在ANSI C的任何⼀种实现中&#xff0c;存在两个不同的环境。 1&#xff09;翻译环境&#xff1a;将源代码被转换为可执行的机器指令 2&#xff09;执行环境&#xff1a;实际执行代码。 1.翻译环境 首先我们来将翻译环境 翻译环境是由 编译 和 链接 两个大的过程…

龙哥的问题(积性函数,莫比乌斯反演)

题目路径&#xff1a; 221. 龙哥的问题 - AcWing题库 思路&#xff1a;

5G消息一站式解决方案,实现全新“跳代”应用体验

随着5G技术的普及和深化&#xff0c;通信行业迎来发展的“红利期”。5G消息作为基础短信业务的升级&#xff0c;可通过手机一键开启。不仅支持在原生短信界面发送多种内容&#xff0c;如&#xff1a;语音、视频、图片、地理位置等。还可通过chatbot功能模拟人类智能对话&#x…

2017年认证杯SPSSPRO杯数学建模A题(第一阶段)安全的后视镜全过程文档及程序

2017年认证杯SPSSPRO杯数学建模 A题 安全的后视镜 原题再现&#xff1a; 汽车后视镜的视野对行车安全非常重要。一般来说&#xff0c;汽车的后视镜需要有良好的视野范围&#xff0c;以便驾驶员能够全面地了解车后方的道路情况。同时&#xff0c;后视镜也要使图像的畸变尽可能…

Zoho Survey评价:功能全面,值得一试

通常来讲&#xff0c;我们在使用一款问卷调查制作工具制作问卷时会有哪些需求呢&#xff1f; 用户需求 1、操作简单&#xff0c;易上手。 2、能够满足用户个性化的需求。 3、提供多语言服务。 4、能够帮助发布以及数据收集。 5、简化数据分析 市面上的问卷调查制作工具都…

【法如faro】法如三维激光扫描软件Scene2023下载与安装教程

FARO SCENE 2023是法如中国官方开发的一款相套配的三维数字化存档软件&#xff0c;该软件专门设计用于所有的Focus和第三方激光扫描仪&#xff0c;通过使用实时现场配准、自动对象识别、扫描图像配准和定位功能&#xff0c;能够帮助用户轻松而高效地处理和管理扫描后的数据。 文…

HTTPS协议把什么加密了?

HTTPS&#xff08;Hypertext Transfer Protocol Secure&#xff09;是一种用于在计算机网络上进行安全通信的协议。它的工作原理主要基于以下几个关键步骤&#xff1a; 1. 握手阶段&#xff08;Handshake&#xff09;&#xff1a; - 客户端向服务器发送一个请求&#xff0c…

349. 两个数组的交集(力扣)(OJ题)

题目链接&#xff1a;349. 两个数组的交集 - 力扣&#xff08;LeetCode&#xff09; 个人博客主页&#xff1a;https://blog.csdn.net/2301_79293429?typeblog 专栏&#xff1a;https://blog.csdn.net/2301_79293429/category_12545690.html 给定两个数组 nums1 和 nums2 &a…

十一、常用API——正则表达式

目录 练习1&#xff1a; 正则表达式的作用 正则表达式 字符类&#xff08;只匹配一个字符&#xff09; 预定义字符&#xff08;只匹配一个字符&#xff09; 数量词 类 Pattern 正则表达式的构造摘要 反斜线、转义和引用 字符类 行结束符 组和捕获 Unicode 支持 与…

Spring Boot整合MyBatis-Plus

引言 在现代软件开发中&#xff0c;我们经常需要处理大量的数据。为了有效地管理这些数据&#xff0c;我们需要使用一些强大的框架。其中&#xff0c;Spring Boot和MyBatis-Plus是两个非常流行的框架。Spring Boot是一个基于Spring的开源Java框架&#xff0c;可以用于创建独立…