vue自定义指令

2 篇文章 0 订阅

全局注册

全局注册通过Vue.directive方法进行注册

Vue.directive(指令名称, {
    /**
    * 只调用一次,指令第一次绑定到元素时被调用,在这里可以进行一次性的初始化设置
    * @param {*} el 指令嗦绑定的元素 dom
    * @param {*} binding 指令信息
    * @param {*} vnode 虚拟节点
    * @param {*} oldVnode 旧虚拟节点 仅在 update 和 componentUpdated 钩子中可用
    */
    bind(el, binding, vnode, oldVnode) {
        const { value } = binding; // 传递过来的参数
    },
    // 被绑定的元素插入父节点时调用
    inserted(el, binding, vnode, oldVnode) {
        console.log("inserted阶段", el, binding, vnode, oldVnode);
    },
    // 所在组件的VNdeo更新是调用,但是可能发生在其子VNode更新之前
    update(el, binding, vnode, oldVnode) {
        const { value } = binding
        el.style.color = value
        console.log("update阶段", el, binding, vnode, oldVnode);
    },
    // 在所在组件的VNode及其子VNode全部更新后调用
    componentUpdated(el, binding, vnode, oldVnode) {
        console.log("componentUpdated阶段", el, binding, vnode, oldVnode);
    },
    // 只调用一次 指令与元素解绑时调用
    unbind(el, binding, vnode, oldVnode) {
        console.log("unbind阶段", el, binding, vnode, oldVnode);
    }
})

例子-点击复制

// copy.js
function handler(binding) {
    const text = document.createElement("input");
    text.setAttribute("value", binding.value);
    document.body.appendChild(text);
    text.select();
    try {
        document.execCommand('copy');
        alert("复制成功")
    } catch (error) {
        alert("您的浏览器不支持点击复制到剪贴板");
    }
    text.remove();
}
export default {
    inserted(el, binding) {
        el.addEventListener("click", () => {
            handler(binding)
        })
    },
    unbind(el) {
        el.removeEventListener("click", () => {
            handler(binding)
        });
    }
}
// 注册自定义指令(copy.js)
import copy from "copy.js";
Vue.directive("copy", copy);
// index.vue 中使用
<template>
  <div>
    <button v-copy="copyContent">复制指令</button>
  </div>
</template>
<script>
export default {
    data() {
        return {
            copyContent: "这是复制的内容"
        }
    }
}
</script>

例子-点击防抖

// debounce.js
function handler(callback, delay) {
    let timer = null;
    return function () {
        clearTimeout(timer);
        timer = setTimeout(() => {
            callback()
        }, delay)
    }
}
export default {
    inserted(el, binding) {
        /**
        * handleClick(v-debounce="handleClick")
        * value 就是上述中的 handleClick 方法
        * <button v-debounce:2000="handleClick2s">防抖指令2s</button>
        * arg 就是 2000 这里表示的是防抖间隔2000ms 默认是200ms
        */
        const { value, arg = 200 } = binding;
        el.addEventListener("click", handler(value, arg))
    },
    unbind(el) {
        el.removeEventListener("click", handler)
    }
}
// 注册自定义指令(debounce.js)
import debounce from "debounce.js";
Vue.directive("debounce", debounce);
// index.vue 中使用
<template>
  <div>
    <button v-debounce="handleClick">防抖指令</button>
    <!-- :后面的就是附带的指令信息 可以在自定义指令中通过arg拿到 -->
    <button v-debounce:2000="handleClick2s">防抖指令2s</button>
  </div>
</template>
<script>
export default {
    data() {
        return {}
    },
    methods: {
        handleClick() {
            console.log("防抖默认 200ms")
        },
        handleClick2s() {
          console.log("防抖2s");
        }
    }
}
</script>

例子-节流

// throttle.js 节流指令
function handler(callback, delay) {
    let timer = null;
    return function () {
        if (timer) return
        timer = setTimeout(() => {
            callback();
            clearTimeout(timer);
            timer = null;
        }, delay)
    }
}
export default {
    inserted(el, binding) {
        // value 就是事件处理函数 即这个指令触发后会执行的函数体
        const { value, arg, modifiers } = binding;
        // 节流间隔时间 默认 200ms
        let delay = arg ?? 200;
        /**
        * <input type="text" v-throttle.keyup="handleThrottle" />
        * modifiers的值是一个对象 key是keyup 值是true 但是需要这个key
        * 所以通过对象的方法Object.keys拿到这个对象的所有key再取第一个 拿来作为我们的事件类型
        */
        let event = Object.keys(modifiers)[0];
        el.addEventListener(event, handler(value, delay))
    },
    unbind(el) {
        let event = Object.keys(modifiers)[0];
        el.removeEventListener(event, handler);
    }
}
// 注册自定义指令(throttle.js)
import debounce from "throttle.js";
Vue.directive("throttle", throttle);
// index.vue 中使用
<template>
  <div>
    <input type="text" v-throttle.keyup="handleThrottle" />
    <button v-throttle:1000.click="handleThrottle1s">节流1s</button>
  </div>
</template>
<script>
export default {
    data() {
        return {}
    },
    methods: {
       handleThrottle1s() {
          console.log("click节流1s");
        },
        handleThrottle() {
          console.log("keyup节流触发");
        }
    }
}
</script>

当我们注册了多个全局指令时,我们需要一个一个的去引入再注册,这是非常麻烦的,所以我们可以将指令文件放在单独的一个文件夹中

然后我们在index.js中批量注册

// 批量注册自定义指令
import Vue from "vue";
const files = require.context("./modules", false, /\.js$/);
const names = files.keys();
for (const filename of names) {
    const config = files(filename);
    const name = filename.replace(/^\.\//, '').replace(/\.js$/, '');
    Vue.directive(name, config.default || config)
}

然后在main.js中引入这个index.js文件即可

// main.js
import "@/directives/index";

这样就完成了全局指令的批量注册

局部指令注册

// index.vue 中
<template>
  <div>
    <input type="text" v-focus>
  </div>
</template>
<script>
export default {
    data() {
        return {}
    },
    directives: {
        focus: {
            inserted(el) {
                el.focus(); // 自动聚焦
            }
        }
    }
}
</script>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值