持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第27天,点击查看活动详情
前情提要
- 对于vue的指令大家应该耳熟能详,像v-model, v-on, v-for, v-if, v-else, v-key等等都是属于vue的指令。但是除此之外在我们实际的业务开发过程中为了方便我们的开发,我们可能还需要另外的自定义一个指令方便我们的开发。那么今天就来聊聊自定义指令相关的东西...
- 基于vue2.x哦
什么是自定义指令
自定义指令是Vue向开发者开放的一个拓展功能。我们可以通过自定义指令实现vue没有提供且具有深度定制化的需求。比如实现一键copy功能,还有指令级的防抖实现等等还有很多都可以通过自定义指令来实现。
自定义指令的生命周期
- 对于自定义指令存在五个声明周期,分别是:
- bind:指令第一次绑定到元素的时候调用,且只调用一次,有点类似类里面的constructor,我们可以在这里面做一些初始化的操作。一般情况下我们其实也就只用了这一个钩子,其他的相对用的少一些。
- inserted:当绑定的组件插入到父节点的时候调用。
- update:当Vnode发生变化的时候调用,不过存在一种情况,就是vnode可能改变了也可能没有改变,所以我们需要对比更改前后的值来判断是否执行后面的代码。
- componentUpdated: 当被绑定的组件所在的组件更新的时候被调用
- unbind: 与bind相对立,只调用一次,解绑的时候调用。如果我们在bind里注册了事件,那么我们可以在这里面进行事件的解绑。
- 差点忘了说一个重要的东西了。上面的五个钩子函数都接收三个参数:
- el:dom实例
- bindding:是一个对象,包含六个属性
- name:当前自定义指令的指令名称。
- value:用户使用我们自定义的指令时所给的值。比如:v-xx="yyyy",xx是我们自定义的值,yyyy是用户给的值
- oldValue:上次给的值
- arg:传给指令的参数。比如:v-xx:zz="yyyy",zz就是传给指令的参数
- modifiers: 包含修饰符的对象。比如:v-xx.stop.enter=“yyyy”,那么该属性时一个对象:{ stop: true, enter: true }
- vnode: Vue编译生成的虚拟dom节点
- oldVnode: 上一次生成的虚拟dom节点
- 指令分为全局指令和组件级指令。
- 全局指令通过:Vue.directive('', {})来实现
- 组件级的通过与methods同级创建一个名为:directives的对象来实现。
自定义指令的应用场景
其实可以使用自定义指令的场景有很多,只不过有些场景我们需要评估相对于自己的项目结构和需求是否最优。
- 场景:
- 组件聚焦和失去焦点的时候我们可以做一些操作,比如出现动画,或者埋点的相关操作。
- 实现指令级的防抖。
- 图片或者视频的懒加载等
- 有些按钮的埋点等
- 一键copy等
- ...
如何实现一个自定义指令
我们说了那么多,该如何去实现一个自定义指令呢?
-
下面我们开始实现一个的节流事件。
- 场景是提交按钮,有时候可能存在被用户连续点击多次提交的问题。默认1秒钟
Vue.directive('buttonThrottle', { bind(el, bindding, vnode) { const event = bindding.arg; // 事件名称 const fn = bindding.value; // 事件的方法 let timer; el.addEventListener(event, e => { if (!timer) timer = setTimeout(() => { fn(); timer = null; }, 1000); }) } }) -
之后我们将该指令放到main.js文件中进行注册
-
然后我们创建一个按钮(复用的前面实现vue-router demo的的项目)
-
之后我们操作看看:
-
大功告成
总结
对于有些需求,自定义指令可以实现,用其他的方式也可以实现,那么我们就需要考虑哪种方式是最优的方式了。没有哪一种方式是最优的,只有相对于需求而言才有最优这个说法。