1.vue2的自定义指令

Vue 在除了提供默认内置的指令外,还允许开发人员根据实际情况自定义指令.

在Vue的项目中,大多数情况下,你都可以操作数据来修改视图,也就是所谓的操作DOM,但是还是避免不了偶尔要操作原生DOM,当我们需要操作DOM的时候,就可以使用到自定义指令。

当然也能用 $refs,实现页面的输入框自动聚焦:

<template>
   <input ref="input" />
</template>

<script>
  export default {
    mounted() {
      this.$refs.input.focus();
    }
  }
</script>

代码基本能实现我们需要的功能,但是如果有很多页面都需要这个功能,那我们就只能是复制这段代码了,而通过自定义指令我们就能解决这种问题。

使用指令来实现:

Vue.directive('focus', {
  bind() {},
  inserted(el) {
    el.focus()
  },
  update() {},
  componentUpdated() {},
  unbind() {}
})

我们通过全局Vue实例注册一个自定义指令,然后通过 v-focus 绑定到需要聚焦的 input 元素上。如果其他组件或模块也需要聚焦功能,只要简单的绑定此指令即可。

<template>
   <input v-focus />
</template>

自定义指令能给我们带来很大的便利,在 Vue2 中给一个指令定义对象可以提供 bindinsertedupdatecomponentUpdatedunbind 五个钩子函数。

什么时候需要自定义指令?

  • 需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。
  • 需要将某些功能在指定DOM元素上使用,但对于需要操作大量DOM元素或者大变动时候,推荐使用组件,而不是指令。

但是在新发布的 Vue3 中对指令也做了一些改造.

2.Vue3中的指令

bind => beforeMount

inserted => mounted

beforeUpdate: 新的钩子,会在元素自身更新前触发

update => 移除!

componentUpdated => updated

beforeUnmount: 新的钩子,当元素自身被卸载前触发

unbind => unmounted
在vue3中指令定义对象可以提供如下几个钩子函数(按需引入):

  • created :绑定元素属性或事件监听器被应用之前调用。该指令需要附加需要在普通的 v-on 事件监听器前调用的事件监听器时,这很有用。

  • beforeMounted :当指令第一次绑定到元素并且在挂载父组件之前执行。

  • mounted :绑定元素的父组件被挂载之后调用。

  • beforeUpdate :在更新包含组件的 VNode 之前调用。

  • updated :在包含组件的 VNode 及其子组件的 VNode 更新后调用。

  • beforeUnmounted :在卸载绑定元素的父组件之前调用

  • unmounted :当指令与元素解除绑定且父组件已卸载时,只调用一次。

Vue3 Vue2
created
beforeMount bind
mounted inserted
beforeUpdate update
updated componentUpdated
beforeUnmount
unmounted unbind

vue3改造后的生命周期钩子变成了七个,而且名称变得比较好记了

2.1全局的自定义指令

在 vue3 中,vue 实例通过createApp 创建,所以全局自定义指令的挂载方式也改变了, directive 被挂载到 app上。

例如定义一个指令改指定元素的颜色.

import { createApp } from 'vue'
import App from './App.vue'
var app = createApp(App)
app.directive("fouce", {
  created(el, binding) { 
      console.log(el, binding);
    el.style.color = binding.value;
  },
  updated(el, binding) { 
     el.style.color = binding.value;
  }

})
app.mount('#app');

在组件中直接使用:

<template>
    <h3 v-colos="'red'">自定义全局指令</h3>
</template>

除了直接在man.js中书写之外还可以外部引用:

实现格式化时间的指令:

创建dayTime.js

import dayjs from 'dayjs'

export default function (app) {
  app.directive('focus', {
    mounted(el) {
      el.focus()
    }
  })
  app.directive('format-time', {
    mounted(el, binding) {
      //console.log(binding.value);
      const time = el.textContent * 1
      el.textContent = dayjs(time).format(binding.value || 'YYYY-MM-DD HH:mm:ss')
    }
  })

}

在main.js中引入

import timeFormat from "./utils/dayTime"
var app = createApp(App)
timeFormat(app);

在组件中使用:

<input type="text" v-focus>
 <h3 v-format-time="'YYYY-MM-DD hh:mm:ss'">1648626494687</h3>

2.2自定义指令钩子函数的参数

钩子函数被赋予了以下参数:

  • el:指令所绑定的元素,可以直接操作DOM。
  • binding:是一个对象,包含该指令的所有信息。

binding 包含的属性具体的分别为:

  • arg 自定义指令的参数名。
  • value 自定义指令绑定的值。
  • oldValue 指令绑定的前一个值。
  • dir 被执行的钩子函数
  • modifiers:一个包含修饰符的对象。

2.3自定义指令参数

自定义指令的也可以带参数,参数可以是动态的,参数可以根据组件实例数据进行实时更新。

例如:根据用户传入的指令参数实现当前的定位

//man.js:

app.directive("locations", {
  created(el, binding) { 
    el.style.position = "relative";
    el.style[binding.arg] = binding.value + "px";
  }
})

//组件:
<template lang="">
  <div>
    <h3 v-colos="'red'">全局自定义指令</h3>
    <span v-locations:left="200">全局自定义指令:实现距离左侧200px</span>
    <p v-locations:top="300" v-colos="'purple'" >全局自定义指令:实现距离顶部300px</p>
  </div>
</template>

2.4局部指令

普通js中使用

<script>

  export default {
     directives:{
       autoFocus: {
          mounted(el) {
          el.focus()
         }      
        }
     },
     setup(props) {

     }

  }
</script>

setup语法糖中使用:

// 注册一个局部的自定义指令,需要以小写v开头
const vFocuss = {
  mounted(el) {
    // 获取input,并调用其focus()方法
   el.focus()
  }
}

//组件
 <input type="text" v-focuss>
文档更新时间: 2023-08-11 15:15   作者:董老师