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

一、在单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')

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis(01)——常用指令

基础指令 select 数字&#xff1a;切换到其他数据库flushdb&#xff1a;清空当前数据库flushall&#xff1a;清空所有数据库dbsize&#xff1a;查看数据库大小exists key1[key2 …]&#xff1a;判断当前的key是否存在keys *&#xff1a;查看所有的keyexpire key 时间&#xff…

智慧校园统一信息门户平台介绍

统一信息门户平台是以统一身份认证平台为基础,将校内分散、异构的应用和信息资源进行整合,通过统一的访问入口,实现各种应用系统的无缝接入和集成,并围绕校内人员之间的人际关系,构建一个支持信息访问、传递、以及协作的集成化环境,实现个性化业务应用的高效开发、集成、…

Python使用graphviz绘制模块间数据流

graphviz官方参考链接&#xff1a; http://www.graphviz.org/documentation/ https://graphviz.readthedocs.io/en/stable/index.html 文章目录 需求描述环境配置实现思路代码实现 需求描述 根据各模块之间的传参关系绘制出数据流&#xff0c;如下图所示&#xff1a; 并且生成…

LabVIEW扫描探针显微镜系统开发

在纳米技术对高精度材料特性测量的需求日益增长。介绍了基于LabVIEW开发的扫描探针显微镜&#xff08;SPM&#xff09;系统。该系统不仅可以高效地测量材料的热物性&#xff0c;还能在纳米尺度上探究热电性质&#xff0c;为材料研究提供了强大的工具。 系统基于扫描探针显微技…

自我摸索:如何运营并玩转CSDN?

自注册CSDN以来已有七年之久&#xff0c;但真正运营CSDN也是最近一年的事情&#xff0c;大概就是22年底&#xff0c;参加2022 博客之星 的竞选。接触了很多大佬&#xff0c;也学习模仿着开始玩转CSDN&#xff0c;虽然没有同期运营的大佬们玩的6&#xff0c;但也有一些经验可以来…

【JavaEE进阶】实现验证码

文章目录 &#x1f332;实现说明&#x1f343;Kaptcha插件介绍&#x1f6a9;插件原理&#x1f6a9;引入依赖&#x1f6a9;⽣成验证码&#x1f6a9;Kaptcha详细配置 &#x1f340;准备⼯作&#x1f334;约定前后端交互接⼝&#x1f6a9;需求分析&#x1f6a9;接⼝定义&#x1f6…

【算法练习Day50】下一个更大元素II接雨水

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 下一个更大元素II接雨水单调…

Java毕业设计第90期-基于springboot的学习英语管理系统

获取源码资料&#xff0c;请移步从戎源码网&#xff1a;从戎源码网_专业的计算机毕业设计网站 项目介绍 基于springboot的学习英语管理系统&#xff1a;前端 thymeleaf、jquery&#xff0c;后端 maven、springmvc、spring、mybatis&#xff0c;角色分为管理员、用户&#xff…

小程序进阶学习(音乐首页-轮播图)

轮播图 样式 轮播图的重点是轮播图的大小&#xff0c;因为每个手机的屏幕大小不一样&#xff0c;但是轮播图的大小是固定的就需要一些技术获取到手机的轮播图大小&#xff0c;然后再设置图片的大小和轮播图边框的大小。 页面代码 <van-searchvalue"{{ value }}"s…

PID笔记

Improving the Beginner’s PID 参考资料 Improving the Beginner’s PID – Introduction The Beginner’s PID 以下是每个人第一次学习的PID方程&#xff1a; 这导致几乎每个人都编写了以下PID控制器&#xff1a; /*working variables*/ unsigned long lastTime; double…

【c++函数重载】

文章目录 一. 命名空间二 .全缺省参数和半缺省参数三 . 函数重载 一. 命名空间 1.不指定域&#xff1a;先在局部找&#xff0c;再全局。 2. 指定域&#xff1a;到指定的命名空间去找。 3. 当把指定命名空间放开时&#xff0c;即using namespace std&#xff1b;例如放开标准c库…

聊聊Java虚拟机(一)—— 类加载子系统

1. 前言 ​ 虚拟机就是一款用来执行虚拟计算机指令的计算机软件。它相当于一台虚拟计算机。大体上&#xff0c;虚拟机分为系统虚拟机和程序虚拟机。系统虚拟机就相当于一台物理电脑&#xff0c;里面可以安装操作系统&#xff1b;程序虚拟机是为了执行单个计算机程序而设计出来…

imgaug库图像增强指南(32):塑造【雪景】效果的视觉魔法

引言 在深度学习和计算机视觉的世界里&#xff0c;数据是模型训练的基石&#xff0c;其质量与数量直接影响着模型的性能。然而&#xff0c;获取大量高质量的标注数据往往需要耗费大量的时间和资源。正因如此&#xff0c;数据增强技术应运而生&#xff0c;成为了解决这一问题的…

蓝桥杯练习题(十二)

&#x1f4d1;前言 本文主要是【算法】——蓝桥杯练习题&#xff08;十二&#xff09;的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他…

【蓝桥杯日记】复盘篇一:深入浅出顺序结构

&#x1f680;前言 本期是一篇关于顺序结构的题目的复盘,通过复盘基础知识&#xff0c;进而把基础知识学习牢固&#xff01;通过例题而进行复习基础知识。 &#x1f6a9;目录 前言 1.字符三角形 分析&#xff1a; 知识点&#xff1a; 代码如下 2. 字母转换 题目分析: 知…

加固密码安全:保护您的个人信息

一、引言 在数字化时代&#xff0c;密码安全是保护个人信息和数据的重要环节。然而&#xff0c;许多人在创建和管理密码时存在一些常见的安全漏洞&#xff0c;如使用弱密码、重复使用密码等。本文将详细介绍密码安全的重要性&#xff0c;并提供一些有效的方法和技巧&#xff0…

使用DALL-E 3模型模拟AI女友的一天 |【人人都是算法专家】

Rocky Ding 公众号&#xff1a;WeThinkIn 知乎&#xff1a;Rocky Ding 写在前面 【人人都是算法专家】栏目专注于分享AI行业中业务/竞赛/研究/产品维度的思考与感悟。欢迎大家一起交流学习&#x1f4aa; 大家好&#xff0c;我是Rocky。 我们都知道DALL-E 3是和Stable Diffusio…

Windows ssh登录eNSP交换机

目录 1. Cloud IO配置1.1 创建UDP端口1.2 创建本地连接1.3 端口映射设置 2. 交换机配置2.1 配置vlanif2.2 配置vty2.3 配置ssh用户2.4 配置aaa2.5 使用Xshell工具登录2.6 用户和密码2.7 登录成功 3. 使用cmd 登录报错提示3.1 手动指定加密算法&#xff0c;提示密码长度无效3.2 …

自定义注解与拦截器实现不规范sql拦截(拦截器实现篇)

最近考虑myBatis中sql语句使用规范的问题&#xff0c;如果漏下条件或者写一些不规范语句会对程序性能造成很大影响。最好的方法就是利用代码进行限制&#xff0c;通过拦截器进行sql格式的判断在自测环节就能找到问题。写了个简单情景下的demo&#xff0c;并通过idea插件来将myB…

Twisted Circuit洛谷绿题题解

Twisted Circuit 题面翻译 读入四个整数 0 0 0 或者 1 1 1&#xff0c;作为如图所示的电路图的输入。请输出按照电路图运算后的结果。 感谢PC_DOS 提供的翻译 题目描述 输入格式 The input consists of four lines, each line containing a single digit 0 or 1. 输出格…