• vue2.x与vue3.x中自定义指令详解


    🐱 个人主页:不叫猫先生
    🙋‍♂️ 作者简介:2022年度博客之星前端领域TOP 2,前端领域优质作者、阿里云专家博主,专注于前端各领域技术,共同学习共同进步,一起加油呀!
    💫优质专栏:vue3 + vite + TypeScript 从入门到实践
    📢 资料领取:前端进阶资料可以找我免费领取
    🔥 摸鱼学习交流:我们的宗旨是在工作中摸鱼,摸鱼中进步,期待大佬一起来摸鱼(文末有我wx或者私信)。

    🌮前言

    vue自定义指令(2.x3.x)可以帮助我们实现需要操作,比如防抖、节流、懒加载、输入框自动聚焦等等,使用起来非常方便,比如vue自带的v-text、v-html、v-show、v-if等等。

    🥙一、自定义指令分类

    • 局部自定义指令:只在组件内有效
    • 全局自定义指令:所有组件都有效

    🥪二、Vue2.x自定义指令钩子函数

    • bind:只会调用一次,指令 第一次 绑定到元素时会调用

    • inserted:被绑定元素插入父节点时调用 。

    • update:元素第一次绑定不会触发,绑定的值发生更新触发,可能发生在其子节点更新之前。

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

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

    (1)bind与update区别

    相同点:

    • dom插入都会调用,bind在inserted之前

    异同点:

    • bind 时父节点为 null
    • inserted 时父节点存在
    • bind是在dom树绘制前调用,inserted在dom树绘制后调用

    (2)update与componentUpdated区别

    • 组件更新都会调用,update在componentUpdated之前
    • update 组件更新前的状态,componentUpdated 组件更新后的状态
    Vue.directive('focus', {
      inserted: function (el) {
        console.log(el.parentNode, 'inserted')
        el.focus();
      },
      bind: function (el) {
        console.log(el.parentNode, 'bind')
        el.focus();
      },
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    输出结果如下,说明执行bind时,还没父节点;执行inserted时,已有父节点。
    在这里插入图片描述

    (3)钩子函数的参数(摘自官网)

    • el:指令所绑定的元素,可以用来直接操作 DOM。
    • binding:一个对象,包含以下 property:
      • name:指令名,不包括 v- 前缀。
      • value:指令的绑定值,例如:v-my-directive=“1 + 1” 中,绑定值为 2。
      • oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
      • expression:字符串形式的指令表达式。例如 v-my-directive=“1 + 1” 中,表达式为 “1 + 1”。
      • arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 “foo”。
      • modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
    • vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
    • oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
     <p v-style:[direction]="connect">Enter connection information to connect</p>
    
    • 1
        directives: {
            style: {
                bind(el,binding) {
                  console.log(binding,'binding')
                    el.style.fontSize = "30px";
                    el.style.color = "blue";
                },
            },
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    (4)局部自定义指令

    在组件A.vue,用自定义指令实现改变文字颜色

    <p v-style>文字描述</p>
    
    • 1
     directives: {
        style: {
          bind(el,binding) {
            el.style.fontSize = "30px";
             el.style.color = "blue";
          },
          update(el,binding){
          el.style.fontSize = "30px";
          el.style.color = "blue";
          }
        },
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • style:指令的名称,使用的时候要加前面加个v-
    • bind:只会调用一次,指令 第一次 绑定到元素时会调用
    • el:是指绑定的这个dom元素本身
    • binding:获取绑定指令的信息(name:指令名称;rawName:指令全称:value:指定绑定的值)
    • update:元素第一次绑定不会触发,绑定的值发生更新触发,参数与binding是相同的,如果逻辑与bind相同的话可以直接把指令当成函数写,上面的指令是对象类型。
    • v-style:使用指令改变了元素的样式

    (5)全局自定义指令

    使用Vue.directive(‘指令名称’,{钩子函数})

    • 第一个参数为字符串,指令的名称
    • 第二个参数是一个对象,用于接收指令的参数值
    Vue.directive('style',{
        bind(el) {
          el.style.fontSize = "30px";
          el.style.color = "blue";
        },
      },
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    (6)简写形式

    如果update逻辑与bind相同的话可以直接把指令当成函数写

     directives: {
        style(){
           el.style.fontSize = "30px";
           el.style.color = "blue";
        },
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    🍔 三、Vue3.x自定义指令钩子函数

    (1)指令钩子函数(摘自官网)

    const myDirective = {
      // 在绑定元素的 attribute 前
      // 或事件监听器应用前调用
      created(el, binding, vnode, prevVnode) {
        // 下面会介绍各个参数的细节
      },
      // 在元素被插入到 DOM 前调用
      beforeMount(el, binding, vnode, prevVnode) {},
      // 在绑定元素的父组件
      // 及他自己的所有子节点都挂载完成后调用
      mounted(el, binding, vnode, prevVnode) {},
      // 绑定元素的父组件更新前调用
      beforeUpdate(el, binding, vnode, prevVnode) {},
      // 在绑定元素的父组件
      // 及他自己的所有子节点都更新后调用
      updated(el, binding, vnode, prevVnode) {},
      // 绑定元素的父组件卸载前调用
      beforeUnmount(el, binding, vnode, prevVnode) {},
      // 绑定元素的父组件卸载后调用
      unmounted(el, binding, vnode, prevVnode) {}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    (2)钩子函数参数

    指令的钩子会传递以下几种参数:

    • el:指令绑定到的元素。这可以用于直接操作 DOM。

    • binding:一个对象,包含以下属性。
      value:传递给指令的值。例如在 v-my-directive=“1 + 1” 中,值是 2。
      oldValue:之前的值,仅在 beforeUpdate 和 updated 中可用。无论值是否更改,它都可用。
      arg:传递给指令的参数 (如果有的话)。例如在 v-my-directive:foo 中,参数是 “foo”。
      modifiers:一个包含修饰符的对象 (如果有的话)。例如在 v-my-directive.foo.bar 中,修饰符对象是 { foo: true, bar: true }。
      instance:使用该指令的组件实例。
      dir:指令的定义对象。

    • vnode:代表绑定元素的底层 VNode。

    • prevNode:之前的渲染中代表指令所绑定元素的 VNode。仅在 beforeUpdate 和 updated 钩子中可用。

    (3)局部注册两种方式

    <script lang="ts" setup>
    // 局部指令, 变量名为驼峰命名(vFocus = v-focus)
    const vFocus = {
      mounted: (el:any) => {
        el.focus()
        console.log(el, '已经自动获得焦点')
      }
    }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    <script lang="ts">
    const vFocus = {
        focus:  {
            mounted(el:any){
                el.focus();
                console.log(el, "已经自动获得焦点");
            }
        },
    };
    export default {
        setup() { },
        directives: vFocus,
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    (4)全局注册

    • 组件A.vue
      <input type="text" v-focus>
    
    • 1
    • 在directives文件夹新建focus.ts文件
    const directives: any = {
    	mounted(el: any) {
    		el.focus();
    		el.value = '1'
    	}
    }
    export default {
    	name: "focus",
    	directives
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 在directives文件夹新建index.js
    import type { App } from 'vue'
    import focus from './focus'
    export default function installDirective(app: App) {
        app.directive(focus.name, focus.directives);
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • main.ts文件
    import directives from './directives'
    const app = createApp(App);
    app.use(directives);
    
    • 1
    • 2
    • 3

    (5)简化形式

    当update和mounted中的函数体一样时,则可以简写成如下:

    const directives = (el:any) => {
    		el.focus();
    		el.value = '1';
    }
    export default {
    	name: "focus",
    	directives
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    每日一练 | 网络工程师软考真题Day43
    java毕业生设计在线点餐系统计算机源码+系统+mysql+调试部署+lw
    PostgreSQL 存储结构浅析
    参考线平滑-FemPosDeviation-SQP
    IDEA: 自用主题及字体搭配推荐
    哈希表的前置知识---二叉搜索树
    YOLO X 改进详解
    [开源精品] C#.NET im 聊天通讯架构设计 -- FreeIM 支持集群、职责分明、高性能
    【菜鸟教程】 C++学习笔记
    ocr、人工智能、文字识别接口
  • 原文地址:https://blog.csdn.net/qq_38951259/article/details/128168041