Vue自定义指令深入探讨实现

来自:网络
时间:2023-05-17
阅读:
目录

指令

想要了解自定义指令,那肯定得先明白什么是指令。

指令的本质:语法糖,标志位。在编译阶段 render 函数里,会把指令编译成 JavaScript 代码。

常见的Vue内置指令有:

  • v-on 即 @。v-on:click=”function“, 缩写为@click=”function“
  • v-if
  • v-for
  • v-html
  • ……

所以指令就是跟我们的元素标签绑定在一起的某些事件,当我们dom组件在一定条件下就会触发相对应的指令。

自定义指令

先看看Vue官方的说法:

除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令。注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令

指令的自定义即我们按照Vue制定的规则去编写一套可以对dom进行操作的功能函数,然后就能与其他Vue的内置指令一样具有一定的功能效果。指令相当于简化了我们对dom的操作,可以快速进行dom的事件处理,当然我们应该尽量减少使用一些容易消耗浏览器资源的指令。

关于注册自定义指令

全局注册

// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时……
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})

局部注册

directives: {
  focus: {
    // 指令的定义
    inserted: function (el) {
      el.focus()
    }
  }
}

自定义指令的钩子函数

bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。

inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。

update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。

componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。

unbind:只调用一次,指令与元素解绑时调用。

封装自定义指令

通过以上的描述,相信大多数人大概对自定义指令以及指令都有了一定的理解,已经可以开始编写一些简单不重复的指令。但是面对一些复杂而且可能需要经常使用到的自定义指令,这个时候我们最好还是把代码进行一层封装,这样可以方便我们后续的修改和有层次的代码编写。

1.首先可以选择在根目录下新建文件夹directive

Vue自定义指令深入探讨实现

2.创建自定义指令的文件夹

Vue自定义指令深入探讨实现

3.文件夹下的index.js文件,例如实现一键复制文本内容,用于鼠标右键粘贴。

const copy = {
  bind(el, { value }) {
    el.$value = value
    el.handler = () => {
      if (!el.$value) {
        // 值为空的时候,给出提示。可根据项目UI仔细设计
        console.log('无复制内容')
        return
      }
      // 动态创建 textarea 标签
      const textarea = document.createElement('textarea')
      // 将该 textarea 设为 readonly 防止 iOS 下自动唤起键盘,同时将 textarea 移出可视区域
      textarea.readOnly = 'readonly'
      textarea.style.position = 'absolute'
      textarea.style.left = '-9999px'
      // 将要 copy 的值赋给 textarea 标签的 value 属性
      textarea.value = el.$value
      // 将 textarea 插入到 body 中
      document.body.appendChild(textarea)
      // 选中值并复制
      textarea.select()
      const result = document.execCommand('Copy')
      if (result) {
        console.log('复制成功') // 可根据项目UI仔细设计
      }
      document.body.removeChild(textarea)
    }
    // 绑定点击事件,就是所谓的一键 copy 啦
    el.addEventListener('click', el.handler)
  },
  // 当传进来的值更新的时候触发
  componentUpdated(el, { value }) {
    el.$value = value
  },
  // 指令与元素解绑的时候,移除事件绑定
  unbind(el) {
    el.removeEventListener('click', el.handler)
  },
}
export default copy

4.directive下需要有一个总管全局directive的文件,便于我们进行全局注册时的操作。

directive/index.js

import copy from './copy'
// 自定义指令
const directives = {
  copy,
}
export default {
  install(Vue) {
    Object.keys(directives).forEach((key) => {
      Vue.directive(key, directives[key])
    })
  },

5.全局进行遍历注册,main.js.Vue.use函数会调用我们写好的install,相当于运行我们install里面的代码

import Vue from 'vue'
import Directives from '@/directive'
Vue.use(Directives)
返回顶部
顶部