本文同步发表在富途web开发团队博客 futu.im/article/vue…javascript
在你初次接触一个新的Javascript框架时,会像第一次进糖果店的孩子同样。给啥拿啥,而更直接点,有些东西可让你更容易成为一个开发者。不可避免的是,咱们在用框架时都会有一个同感,就是总有些场景是框架不能帮咱们完成的。css
Vue框架的漂亮之处在于它的功能很是强大,虽然这个框架的指令不够面面俱到,但也能在开发上助你一臂之力了,由于建立一个自定义指令是很轻松的。html
我在Vue.js guide中写过指令的一篇文章,如今再一块儿复习下。vue
指令是能够写在DOM元素的小命令,他们以v-
为前缀,vue就能识别这是一个指令并保持语法的一致性。若是你须要对HTML进行底层操做的话,这种方式是很是有用的。java
若是你已经用过vue或者angular的话,对于v-if
,v-else
,v-show
等指令就会比较熟悉了,可是我仍是要介绍一些基础的知识,若是你更想直接看例子,能够直接看后文就行了。node
如下是使用指令的几种方法,以及示例,这些例子并不规范,它们只是示例。这里的example
代替了实际的指令。web
v-example
- 会实例化一个指令,但这个指令没有参数。若是不传参数会比较不灵活,可是这样就已经操做DOM元素的能力了。vue-cli
v-example="value"
- 这样能够传值到指令中,指令会根据value
值来操做html。express
<div v-if="stateExample">stateExample为true时会显示</div>
复制代码
v-example="'string'"
- 使用字符串做为表达式。app
<p v-html="'<strong>this is an example of a string in some text<strong> '"></p>
复制代码
v-example:arg="value"
- 这里能够传参数(arg
),在下面的例子中,咱们绑定一个class
,而后给这个class
设置样式。
<div v-bind:class="someClassObject"></div>
复制代码
v-example:arg.modifier="value"
- 使用修饰符(modifier
),下面的例子能够在click
事件上调用preventDefault()
;
<button v-on:submit.prevent="onSubmit"></button>
复制代码
如今对指令有了大概的了解后,咱们再来学习下如何建立一个自定义指令。自定义指令的典型例子就是建立一个scroll
事件的指令,下面让咱们一块儿来看一下。
首先建立一个单纯的全局指令(它尚未作任何事情)。
vue.directive('tack');
复制代码
根据这个指令HTML就是这样的:
<p v-tack>This element has a directive on it</p>
复制代码
指令定义函数提供了几个钩子函数 (可选):
bind
-只调用一次,指令第一次绑定到元素时调用。insert
-被绑定元素插入父节点时调用。update
-所在组件的 VNode 更新时调用,可是可能发生在其子元素的 VNode 更新以前。componentUpdated
-所在组件的 VNode 及其子元素的 VNode 所有更新时调用。unbind
-只调用一次,指令与元素解绑时调用。我认为这五个钩子函数中bind
和update
是最有用的。
他们中的每个都有能够用的el
,binding
和vnode
参数,除了update
和componentUpdated
以外,还会暴露oldVnode
,以区分传递的旧值和新值。
el
指令所绑定的元素,能够用来直接操做 DOM 。binding
一个对象,包含如下属性:name
,value
,oldValue
,expression
,arg
和modifiers
。vnode
Vue 编译生成的虚拟节点。binding
和vnode
都是只读。
了解了自定义指令概念后,来看下如何使用一个自定义指令,下面用一个例子来实现咱们刚才所说的:
Vue.directive('tack',{
bind(el,binding,vnode){
el.style.position = 'fixed'
}
})
复制代码
相对应的HTML就是:
<p v-tack>I will now be tacked onto the page</p>
复制代码
这样就能够了,可是还不够灵活。若是能接受参数以便后续更新它的表现或者进行复用的话就会更加灵活。让咱们看下如何实现让这个元素离页面顶部有必定的距离:
Vue.directive('tack',{
bind(el,binding,vnode){
el.style.position = 'fixed';
el.style.top = binding.value + 'px';
}
})
复制代码
<div id="app">
<p>向下滚动页面</p>
<p v-tack="70">我固定在离顶部70px的地方</p>
</div>
复制代码
完成后的CodePen展现:(如没法展现效果,点击连接查看)
假设咱们想要区分偏离的70px是在顶部仍是左侧,能够经过传递一个参数来实现:
<p v-tack:left="70">如今我会在距离左侧70px的地方</p>
复制代码
Vue.directive('tack',{
bind(el,binding,vnode){
el.style.position = 'fixed';
const s = (binding.arg == 'left'?'left':top);
el.style[s] = binding.value + 'px';
}
})
复制代码
完成后的CodePen展现:(如没法展现效果,点击连接查看)
你也能够使用多个值,像自带指令同样用:
<p v-tack="{top:'40',left:'100'}">我固定在离顶部40px、左侧100px的地方</p>
复制代码
而后这两个值将会在指令上同时生效:
Vue.directive('tack',{
bind(el,binding,vnode){
el.style.position = 'fixed';
el.style.top = binding.value.top+'px';
el.style.left = binding.value.left+'px';
}
})
复制代码
完成后的CodePen展现:(如没法展现效果,点击连接查看)
咱们还能够编写更复杂的东西,咱们能够根据自定义指令来建立和修改方法。这里,咱们简单建立一个滚动动画小例子:
Vue.directive('scroll',{
inserted:function(el,binding){
let f = function(evt){
if(binding.value(evt,el)){
window.removeEventListener('scroll',f);
}
}
window.addEventListener('scroll',f);
}
});
//main app
new Vue({
el:'#app',
methods:{
handleScroll:function(evt,el){
if(window.scrollY>50){
TweenMax.to(el,1.5,{
y:-10,
opacity:1,
ease:sine.easeOut
})
}
return window.scrollY>100;
}
}
});
复制代码
<div class="box" v-scroll="handleScroll">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. A atque amet harum aut ab veritatis earum porro praesentium ut corporis. Quasi provident dolorem officia iure fugiat, eius mollitia sequi quisquam.</p>
</div>
复制代码
完成后的CodePen展现:(如没法展现效果,点击连接查看)
以上都是很简单的代码来实现效果,在实际的开发中,你能够建立更高级灵活的自定义指令。
在一个实际构建过程当中,我会将指令代码放在main.js
中,这个文件位于src
目录下(若是你使用的是vue-cli这样的工具的话),这样App.vue
及以.vue
后缀名的文件均可以引入使用。你固然也能够使用其余的方式,但这是我认为在实现整个App过程当中最灵活的方式。
若是你想了解有关Vue框架的更多知识,请查看guide.
原文:The Power of Custom Directives in Vue
译者:Diandian