Vue中内置了很多的指令,如v-model、v-show、v-html等,但是有时候这些指令并不能满足我们,或者说我们想为元素附加一些特别的功能,这时候,我们就需要用到vue中一个很强大的功能了—自定义指令。
自定义指令里的钩子函数
options = { bind:function(el,binding,vnode){ }, inserted:function(el,binding,vnode){ }, update:function(el,binding,vnode){ }, componentUpdated:function(el,binding,vnode){ }, unbind:function(el,binding,vnode){ }, }
对于全局自定义指令的创建,我们需要使用 Vue.directive
接口
Vue.directive('myd', options)
对于局部组件,我们需要在组件的钩子函数directives中进行声明
directives: { myd: options }
下面是简单写的两个例子,v-click实现点击时间超过150毫秒不执行跳转,v-scroll实现下拉滚动条改变div-main的距离顶部高度
directives: { click: { inserted(el, binding, vnode) { let timestamp = 0; el.onmousedown = function() { timestamp = Date.now(); }; el.onclick = function() { if ((Date.now() - timestamp) > 150) return; // 执行跳转 vnode.context.viewUserGroupDetail(binding.value); }; } }, scroll: { inserted(el, binding) { const onScroll = () => { document.querySelector('#div-main' + binding.value).style.top = el.scrollTop + 'px'; }; el.handler = onScroll; el.addEventListener('scroll', onScroll); }, unbind(el) { document.removeEventListener('scroll', el.handler); } } },
动态指令参数
指令的参数可以是动态的。例如,在 v-mydirective:[argument]="value"
中,argument
参数可以根据组件实例数据进行更新!这使得自定义指令可以在应用中被灵活使用。
例如你想要创建一个自定义指令,用来通过固定布局将元素固定在页面上。我们可以像这样创建一个通过指令值来更新竖直位置像素值的自定义指令:
官网给的例子
<div id="baseexample"> <p>Scroll down the page</p> <p v-pin="200">Stick me 200px from the top of the page</p> </div> Vue.directive('pin', { bind: function (el, binding, vnode) { el.style.position = 'fixed' el.style.top = binding.value + 'px' } }) new Vue({ el: '#baseexample' })
这会把该元素固定在距离页面顶部 200 像素的位置。但如果场景是我们需要把元素固定在左侧而不是顶部又该怎么办呢?这时使用动态参数就可以非常方便地根据每个组件实例来进行更新。
<div id="dynamicexample"> <h3>Scroll down inside this section ↓</h3> <p v-pin:[direction]="200">I am pinned onto the page at 200px to the left.</p> </div> Vue.directive('pin', { bind: function (el, binding, vnode) { el.style.position = 'fixed' var s = (binding.arg == 'left' ? 'left' : 'top') el.style[s] = binding.value + 'px' } }) new Vue({ el: '#dynamicexample', data: function () { return { direction: 'left' } } })