前言css
不少事情不能作过多的计划,由于计划赶不上变化。今日早读文章由富途@点点翻译分享。html
正文从这开始~前端
在你初次接触一个新的Javascript框架时,会像第一次进糖果店的孩子同样。给啥拿啥,而更直接点,有些东西可让你更容易成为一个开发者。不可避免的是,咱们在用框架时都会有一个同感,就是总有些场景是框架不能帮咱们完成的。vue
Vue框架的漂亮之处在于它的功能很是强大,虽然这个框架的指令不够面面俱到,但也能在开发上助你一臂之力了,由于建立一个自定义指令是很轻松的。node
什么是指令?vue-cli
我在Vue.js guide中写过指令的一篇文章,如今再一块儿复习下。express
指令是能够写在DOM元素的小命令,他们以v-为前缀,vue就能识别这是一个指令并保持语法的一致性。若是你须要对HTML进行底层操做的话,这种方式是很是有用的。app
若是你已经用过vue或者angular的话,对于v-if,v-else,v-show等指令就会比较熟悉了,可是我仍是要介绍一些基础的知识,若是你更想直接看例子,能够直接看后文就行了。框架
如下是使用指令的几种方法,以及示例,这些例子并不规范,它们只是示例。这里的example代替了实际的指令。ide
v-example - 会实例化一个指令,但这个指令没有参数。若是不传参数会比较不灵活,可是这样就已经操做DOM元素的能力了。
v-example="value" - 这样能够传值到指令中,指令会根据value值来操做html。
<div v-if="stateExample">stateExample为true时会显示</div>
v-example="'string'" - 使用字符串做为表达式。
<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>
假设咱们想要区分偏离的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';
}
})
你也可使用多个值,像自带指令同样用:
<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';
}
})
咱们还能够编写更复杂的东西,咱们能够根据自定义指令来建立和修改方法。这里,咱们简单建立一个滚动动画小例子:
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>
以上都是很简单的代码来实现效果,在实际的开发中,你能够建立更高级灵活的自定义指令。
在一个实际构建过程当中,我会将指令代码放在main.js中,这个文件位于src目录下(若是你使用的是vue-cli这样的工具的话),这样App.vue及以.vue后缀名的文件均可以引入使用。你固然也可使用其余的方式,但这是我认为在实现整个App过程当中最灵活的方式。
最后,你可能还会看:
【第970期】聊聊vue组件开发的“边界把握”和“状态驱动”
关于本文
译者:@点点
译文:https://futu.im/posts/2017-10-31-vue-cutom-directive/
做者:@SARAH DRASNER
原文:https://css-tricks.com/power-custom-directives-vue/