Axiu Blog
倍的效果。 指令可以通过全局注册,也可以局部注册,这一点和组件类似。 指令提供了几个钩子函数,主要是`bind`(绑定到元素时调用)、`unbind`(解绑时调用)、`inserted`(被绑定元素插入到父节点时调用)、`update`(被绑定元素所在的模版更新时调用)、`componentUpdate`(被绑定元素所在模版完成一次更新周期时调用)。这几
Vue里`v-model`和`v-show`等都属于核心指令,除此之外,也可以自己写一些自定义指令。虽然和组件(components)比起来,这些属于锦上添花的小技巧,不过对于大面积的使用,抽取出一些公共方法,放到指令里,有时候能起到事半功倍的效果。 指令可以通过全局注册,也可以局部注册,这一点和组件类似。 指令提供了几个钩子函数,主要是`bind`(绑定到元素时调用)、`unbind`(解绑
Vue里`v-model`和`v-show`等都属于核心指令,除此之外,也可以自己写一些自定义指令。虽然和组件(components)比起来,这些属于锦上添花的小技巧,不过对于大面积的使用,抽取出一些公共方法,放到指令里,有时候能起到事半功倍的效果。 指令可以通过全局注册,也可以局部注册,这一点和组件类似。 指令提供了几个钩子函数,主要是`bind`(绑定到元素时调用)、`unbind`(解绑
Vue:指令(directive)简介
Max

Vue里v-modelv-show等都属于核心指令,除此之外,也可以自己写一些自定义指令。虽然和组件(components)比起来,这些属于锦上添花的小技巧,不过对于大面积的使用,抽取出一些公共方法,放到指令里,有时候能起到事半功倍的效果。

指令可以通过全局注册,也可以局部注册,这一点和组件类似。

指令提供了几个钩子函数,主要是bind(绑定到元素时调用)、unbind(解绑时调用)、inserted(被绑定元素插入到父节点时调用)、update(被绑定元素所在的模版更新时调用)、componentUpdate(被绑定元素所在模版完成一次更新周期时调用)。这几个钩子函数的参数:el(指令绑定的元素)、bindingvnodeoldVnode,其中binding是个很有意思的参数。

官方给的说明

binding: 一个对象,包含以下属性:
name: 指令名,不包括 v- 前缀。
value: 指令的绑定值, 例如: v-my-directive=”1 + 1″, value 的值是 2。
oldValue: 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
expression: 绑定值的字符串形式。 例如 v-my-directive=”1 + 1″ , expression 的值是 “1 + 1″。
arg: 传给指令的参数。例如 v-my-directive:foo, arg 的值是 “foo”。
modifiers: 一个包含修饰符的对象。 例如: v-my-directive.foo.bar, 修饰符对象 modifiers 的值是 { foo: true, bar: true }。

这个binding,可以说是打通整个指令数据‘通路’的关键部分。用binding.value取到指令传入的参数(或函数名),并可以用binding.expression取到字面量。

到这里,指令的任务就可以猜到了。比如直接在bind里,实现el这个DOM元素的操作,比如获取焦点,收缩/展开,执行个特定的动画什么的。

或者更进一步,对binding里的东西操作一下。比如通过value传入一个函数,通过arg传入具体参数,用modifiers设置一些标志位。这样,既可以实现执行函数的目的,又有一定的灵活度。

举个栗子

new Vue({ el: "#app", data:{ show: false }, methods:{ clickedOutside: function () { this.show = false; } }, directives: { 'click-outside':{ bind: function (el, binding, vNode) { // Provided expression must evaluate to a function. if (typeof binding.value !== 'function') { var compName = vNode.context.name; var warn = '[Vue-click-outside:] provided expression ' + binding.expression + ' is not a function, but has to be'; if (compName) { warn += 'Found in component ' + compName; } console.warn(warn); } // Define Handler and cache it on the element var handler = function(e) { if (!el.contains(e.target) && el !== e.target) { binding.value(e); } }; el.__vueClickOutside__ = handler; // add Event Listeners document.addEventListener('click', handler); }, unbind: function (el, binding) { // Remove Event Listeners document.removeEventListener('click', el.__vueClickOutside__); el.__vueClickOutside__ = null; } } } })

html

  • 社区

    ......

这个示例用于实现“点击父元素展开子栏目,点击屏幕任意地方收起子栏目”的效果。放到了github:地址,可以直接copy到工程里或者clone下来看看效果。

bind里,添加click事件监听器。
当判断click事件的target不是绑定元素的子元素,即点击到了其他地方,此时通过binding.value(e)来调用methods里声明的clickedOutside函数,使show = false,达到隐藏的目的。

在unbind里,移除监听器。

总结

相比较于组件,指令看起来简单很多。并且通常不涉及到数据的传递,只是会通过arg传入参数。所以对于指令间的数据传递,官方给出的方式是通过attribute来传递。所以,指令可能真的如字面意义,就是“指令”,绑定或执行一下就可以了。

Comments