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

这篇具有很好参考价值的文章主要介绍了【学习记录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、实现效果

【学习记录24】vue3自定义指令,学习,vue.js,javascript

二、全局注册使用

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)

 【学习记录24】vue3自定义指令,学习,vue.js,javascript

 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文章来源地址https://www.toymoban.com/news/detail-804984.html

// 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')

到了这里,关于【学习记录24】vue3自定义指令的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vue3 图片放大缩小、拖拽功能(自定义指令)

    效果 自定义 拖拽指令 vDrag.js 参考来源 https://github.com/sunzsh 使用 自定义 拖拽指令 写法二 (带传参及回调写法) vDrag.js 使用 自定义 缩放指令 vWheelScale.js 根据项目需要 我指令加了 动态参数 及 回调函数 不需要自行修改 使用 自定义 缩放指令 写法二(带传参及回调写法)

    2024年02月01日
    浏览(36)
  • Vue.js 2.0 自定义指令

    除了默认设置的核心指令( v-model 和 v-show ),Vue 也允许注册自定义指令。注意,在 Vue2.0 里面,代码复用的主要形式和抽象是组件——然而,有的情况下,你仍然需要对纯 DOM 元素进行底层操作,这时候就会用到自定义指令。下面这个例子将聚焦一个 input 元素,像这样: 当页面

    2023年04月19日
    浏览(41)
  • 两周掌握Vue3(五):自定义指令、路由、ajax

    代码仓库:跳转 当前分支:05 自定义指令是Vue.js框架提供的一个非常强大的特性,它允许开发者直接操作DOM,扩展Vue.js的能力。自定义指令的主要作用包括: 封装常用操作 :当你发现在多个组件中需要重复执行相同的DOM操作时,可以将这些操作封装成一个自定义指令,以提

    2024年01月15日
    浏览(29)
  • Vue3实现图片懒加载及自定义懒加载指令

    大家好,我是南木元元,热衷分享有趣实用的文章。图片懒加载是一种常见性能优化的方式,它只去加载可视区域图片,而不是在网页加载完毕后就立即加载所有图片,能减少很多不必要的请求,极大的提升用户体验。 图片懒加载的 实现原理 :在图片没进入可视区域的时候

    2024年02月13日
    浏览(23)
  • vue3 封装自定义指令,监听元素宽高的变化

    最近做一个项目,涉及到echart图,要去根据父元素去自适应宽高,所以需要监听到元素的宽高变化、 因为是 监听某一元素的宽高变化 ,所以这里用的是 ResizeObserver. ResizeObserver 是可以监听到DOM元素,宽高的变化,需要注意的一点就是监听出变化结果是contentBox的宽度和高度。

    2024年02月07日
    浏览(33)
  • vue自定义指令v-loading(vue2和vue3)

      1. 目录结构: 2. 代码实现  /directives/loading/loading.vue    loading效果页面(此处使用的antd下面的组件,可自定义) /directives/loading/loading.js (实现loading组件的插入及销毁) /directives/loading/index.js (loading指令的注册) 3. 全局引入(main.js文件) 4. 使用 1. 目录结构 2. 代码实现

    2023年04月23日
    浏览(79)
  • 【Vue3.0 ——指令学习】

    v-text 期望值是 string v-html 期望值: string 注意:在你的站点上动态渲染任意的HTML是非常危险的,因为他很容易导致XSS攻击。请只对可信内容使用HTML差值,绝不要将用户提供的内容作为插值 scoped将不会作用于v-html,可以使用css modules css modules用法:https://blog.csdn.net/weixin_47416

    2024年02月12日
    浏览(20)
  • 【Vue2.0源码学习】指令篇-Vue自定义指令

    在 Vue 中,除了 Vue 本身为我们提供的一些内置指令之外, Vue 还支持用户自定义指令。并且用户有两种定义指令的方式:一种是使用全局API—— Vue.directive 来定义全局指令,这种方式定义的指令会被存放在 Vue.options[\\\'directives\\\'] 中;另一种是在组件内的 directive 选项中定义专为

    2024年02月09日
    浏览(36)
  • 记录--Vue3自定义一个Hooks,实现一键换肤

    使用CSS变量, 准备两套CSS颜色 , 一套是在 light模式下的颜色,一套是在dark模式下的颜色 dark模式下的 CSS 权重要比 light 模式下的权重高 , 不然当我们给html添加自定义属性 [data-theme=\\\'dark\\\'] 的时候, dark模式权重比light低,会一直不起效果 当我们点击 dark 模式的时候, 给 html 设置自定义

    2024年02月07日
    浏览(28)
  • vue3自定义指令实现超出显示省略号,鼠标浮入弹出title,显示全部文本

    mounted 和 updated 是 Vue 生命周期钩子函数,分别表示 指令挂载到元素 和 指令所在组件更新时触发 。 el : HTMLElement 和 binding : DirectiveBinding 是方法参数, el 表示指令作用的元素, binding 包含指令的绑定值、参数和修饰符等信息。 el.offsetWidth 获取的是元素在渲染时所占据的整体

    2024年02月01日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包