vue3中的自定义指令

使用场景

在vue中,自定义指令可用于定义复杂的行为或公用的行为,以便于在多个组件中重复使用。

例如,如果你想在一个应用中多处使用拖拽功能,你可以定义一个v-draggable指令,某个组件通过使用该指令来为某个元素启用拖拽功能。

另一个例子是,如果你想在一个应用中多处使用格式化日期的功能,你可以定义一个 v-date-format指令,在组件中通过使用该指令来自动格式化日期。

总之,当你想要在多个组件中重用某个复杂的行为或逻辑时,就可以考虑使用自定义指令。

自定义指令

Vue 3 的指令系统与 Vue 2 相比有了一些改变。在 Vue 2 中,指令是一种特殊的 attribute,它们以 v- 为前缀,例如 v-if 和 v-for。

在 Vue 3 中,指令仍然可以用作 attribute,但是它们也可以作为一种新的声明式 API,以 on 开头,例如onBeforeMountonBeforeUpdate

要封装一个自定义指令,首先需要定义一个函数,其中的第一个参数是指令的绑定值,第二个参数是一个包含指令信息的对象。

注册指令 MyComponent.vue

import { directive } from 'vue'

const MyDirective = directive((el, binding) => {
  // 获取指令的值
  const value = binding.value

  // 在指令的钩子函数中执行逻辑
  el.style.color = value
})

export default {
  name: 'MyComponent',
  directives: {
    MyDirective,
  },
}

使用方法:

<template>
  //使用 attribute 形式
  <div v-my-component='red'>Hello, world!</div>
  //使用声明式 API 形式
  <div onMyComponent='red'>Hello, world!</div>
</template>

<script>
  import MyComponent from './MyComponent.vue
</script>

请注意,在声明式 API 中,指令名称的首字母会被自动转换为小写。

将自定义指令注册为组件,全局使用

指令的生命周期和组件类似,首先我们要让指令能够支持 Vue 的插件机制,所以我们需要在 install 函数内注册 lazy 指令。

在 install 方法的内部去注册 lazy 指令,并且实现了 mounted、updated、unmounted 三个钩子函数。

import { createApp } from 'vue'

const MyPlugin = {
  install (app, options) {
    app.directive((el, binding) => {
	  const value = binding.value
	  el.style.color = value
	})
  }
}
const app = createApp(App)
app.use(MyPlugin)

当然,你也可以将自定义指令的插件写的更加优雅,这样无论是可读性还是日后的维护都会非常友好

下面的代码中,我们注册了 loadingDirective 指令,并且注册了 mounted、updated、unmounted 三个钩子函数,通过 v-loading 的值来对显示效果进行切换,实现了组件内部的 loading 状态。

动态切换的 Loading 组件能够显示一个 circle 的 div 标签,通过 v-loading 指令的注册,在后续表格、表单等组件的提交状态中,加载状态就可以很方便地使用 v-loading 来实现。

const loadingDirective = {
  mounted: function (el, binding, vnode) {
    const mask = createComponent(Loading, {
      ...options,
      onAfterLeave() {
        el.domVisible = false
        const target =
          binding.modifiers.fullscreen || binding.modifiers.body
            ? document.body
            : el
        removeClass(target, 'el-loading-parent--relative')
        removeClass(target, 'el-loading-parent--hidden')
      }
    })
    el.options = options
    el.instance = mask.proxy
    el.mask = mask.proxy.$el
    el.maskStyle = {}

    binding.value && toggleLoading(el, binding)
  },

  updated: function (el, binding) {
    el.instance.setText(el.getAttribute('element-loading-text'))
    if (binding.oldValue !== binding.value) {
      toggleLoading(el, binding)
    }
  },

  unmounted: function () {
    el.instance && el.instance.close()
  }
}

export default {
  install(app) {
    // if (Vue.prototype.$isServer) return
    app.directive('loading', loadingDirective)
  }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值