首页

vue2自定义指令和指令的生命周期

kkcode
2023-06-07  阅读 493

指令的周期

5个 (bind、inserted、update、componentUpdated、unbind)。

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

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

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

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

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

注册自定义指令

注册全局指令Vue.directive()

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

注册局部指令directives属性

directives: {
    focus: {
        // 指令的定义
        inserted: function (el) {
            el.focus()
        },
        // ...
    }
}复制代码

案列一

注册一个局部的自定义指令v-append-text:不替换原来的内容,直接插入其后。

<template>
    <div>
        <button @click="show = !show">{{show ? "销毁" : "插入"}}</button>
        <button v-if="show" v-append-text="`hello ${number}`" @click="number++">按钮</button>
    </div>
</template>
<script>
export default {
    directives: {
        // 这里定义一个名为appendText的指令,使用时要像这样去用:v-append-text
        appendText: {
            /**
             * 指令的生命周期 (bind、inserted、update、componentUpdated和unbind)
             **/
            bind(){
                console.log("bind");
            },
            inserted(el, binding){
                el.appendChild(document.createTextNode(binding.value));
                console.log("inserted", el, binding);
            },
            update() {
                console.log("update");
            },
            componentUpdated(el, binding){
                el.removeChild(el.childNodes[el.childNodes.length - 1]);
                el.appendChild(document.createTextNode(binding.value));
                console.log("componentUpdated");
            },
            unbind(){
                console.log("unbind");
            }
        }
    },
    data() {
        return {
            number: 1,
            show: true
        };
    }
}
</script>复制代码

在vue2项目中使用指令

  1. 首先我们可以再src目录下,创建一个directives的文件夹;

  2. 然后在directives文件夹里新建一个globalDirectives.js的文件;

  3. 源码

// globalDirectives.js
const globalDirectives = {
  /*
   * 文字超出省略
   * width:宽度,非必传,默认100%
   * line:超出多少行显示省略号,非必传,默认1行
   * 示例:v-ellipisis="{width:100,line:2}"
   */
  ellipsis: (el, binding) => {
    let { width, line } = binding.value
    el.style.width = width ? width + 'px' : '100%'
    el.style.display = '-webkit-box'
    el.style.overflow = 'hidden'
    el.style.textOverflow = 'ellipsis'
    el.style['-webkit-line-clamp'] = line || 1
    el.style['-webkit-box-orient'] = 'vertical'
  },
  /*
   * 元素吸顶
   * stickyNum:距离顶部多少px吸顶,非必传,默认0
   * 示例:v-sticky="50"
   */
  sticky: {
    bind: (el, { value }) => {
      const stickyNum = value || 0
      window.addEventListener(
        'scroll',
        globalDirectives.sticky.handleScroll(el, stickyNum)
      )
    },
    unbind: () => {
      window.removeEventListener(
        'scroll',
        globalDirectives.sticky.handleScroll()
      )
    },
    handleScroll: (el, stickyNum) => {
      return () => {
        const scrollTop =
          window.scrollY ||
          document.documentElement.scrollTop ||
          document.body.scrollTop
        if (scrollTop >= el.offSetTop - stickyNum) {
          el.style.position = 'sticky'
          el.style.top = stickyNum + 'px'
          el.style.zIndex = 10
        } else {
          el.style.position = 'stick'
        }
      }
    }
  },
  /*
   * 点击事件防抖
   * 参数:事件名称
   * 示例:v-debounce = "eventName"
   */
  debounce: {
    inserted: (el, { value }) => {
      el.addEventListener(
        'click',
        globalDirectives.debounce.debounceEvent(value)
      )
    },
    unbind: (el, { value }) => {
      el.removeEventListener(
        'click',
        globalDirectives.debounce.debounceEvent(value)
      )
    },
    debounceEvent: (value) => {
      let timeout
      return () => {
        if (timeout) clearTimeout
        timeout = setTimeout(() => {
          value()
        }, 500)
      }
    }
  }
}
export default globalDirectives复制代码
  1. 在directives文件夹里新建一个index.js的文件,完成批量定义
  2. 注册全局指令
// index.js

import globalDirectives from './globalDirectives'
const directives = {
  install: function (app) {
    Object.keys(globalDirectives).forEach((key) => {
      app.directives(key, globalDirectives[key])
    })
  }
}

export default directives复制代码
  1. 在main.js引入自定义指令
// main.js

import directives from '@/directives'
Vue.use(directives)复制代码
本文为作者原创文章,转载无需和我联系,但请注明转载链接。 【前端黑猫】