【第1103期】vue 自定义指令的魅力

点点 前端早读课 2017-11-08

前言

很多事情不能做过多的计划,因为计划赶不上变化。今日早读文章由富途@点点翻译分享。

正文从这开始~

在你初次接触一个新的Javascript框架时,会像第一次进糖果店的孩子一样。给啥拿啥,而更直接点,有些东西可以让你更容易成为一个开发者。不可避免的是,我们在用框架时都会有一个同感,就是总有些场景是框架不能帮我们完成的。

Vue框架的漂亮之处在于它的功能非常强大,虽然这个框架的指令不够面面俱到,但也能在开发上助你一臂之力了,因为创建一个自定义指令是很轻松的。

什么是指令?

我在Vue.js guide中写过指令的一篇文章,现在再一起复习下。

指令是可以写在DOM元素的小命令,他们以v-为前缀,vue就能识别这是一个指令并保持语法的一致性。如果你需要对HTML进行底层操作的话,这种方式是非常有用的。

如果你已经用过vue或者angular的话,对于v-if,v-else,v-show等指令就会比较熟悉了,但是我还是要介绍一些基础的知识,如果你更想直接看例子,可以直接看后文就好了。

以下是使用指令的几种方法,以及示例,这些例子并不规范,它们只是示例。这里的example代替了实际的指令。

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组件开发的“边界把握”和“状态驱动”

【第917期】Vue框架引入JS库的正确姿势

关于本文

译者:@点点

译文:https://futu.im/posts/2017-10-31-vue-cutom-directive/

作者:@SARAH DRASNER

原文:https://css-tricks.com/power-custom-directives-vue/

 

vue 自定义指令的魅力的更多相关文章

  1. vue自定义指令

    Vue自定义指令: Vue.directive('myDr', function (el, binding) { el.onclick =function(){ binding.value(); } ...

  2. vue 自定义指令的使用案例

    参考资料: 1. vue 自定义指令: 2. vue 自定义指令实现 v-loading: v-loading,是 element-ui 组件库中的一个用于数据加载过程中的过渡动画指令,项目中也很少需 ...

  3. vue自定义指令(Directive中的clickoutside.js)的理解

    阅读目录 vue自定义指令clickoutside.js的理解 回到顶部 vue自定义指令clickoutside.js的理解 vue自定义指令请看如下博客: vue自定义指令 一般在需要 DOM 操 ...

  4. Vue自定义指令报错:Failed to resolve directive: xxx

    Vue自定义指令报错 Failed to resolve directive: modle 这个报错有2个原因: 1.指令单词拼错 2.Vue.directive() 这个方法没有写在 new Vue ...

  5. vue自定义指令clickoutside使用以及扩展用法

    vue自定义指令clickoutside使用以及扩展用法 产品使用vue+element作为前端框架.在功能开发过程中,难免遇到使用element的组件没办法满足特殊的业务需要,需要对其进行定制,例如 ...

  6. vue自定义指令clickoutside扩展--多个元素的并集作为inside

    都是个人理解,如果发现错误,恳请大家批评指正,谢谢.还有我说的会比较啰嗦,因为是以自身菜鸡水平的视角来记录学习理解的过程,见谅. 1.前言 产品使用vue+element作为前端框架.在功能开发过程中 ...

  7. 每个人都能实现的vue自定义指令

    前文 先来bb一堆废话哈哈.. 用vue做项目也有一年多了.除了用别人的插件之外.自己也没尝试去封装指令插件之类的东西来用. 刚好最近在项目中遇到一个问题.(快速点击按钮多次触发多次绑定的方法),于是 ...

  8. vue自定义指令,比onerror更优雅的方式实现当图片加载失败时使用默认图,提供三种方法

    首先,来看下效果图(演示一下图片正常加载与加载失败时的效果) 在线体验地址:https://hxkj.vip/demo/vueImgOnerror/ 一.常规方法解决 我们都知道,img标签支持one ...

  9. Vue自定义指令使用场景

    当你第一次接触vue的时候,一定会使用到其中的几个指令,比如:v-if.v-for.v-bind...这些都是vue为我们写好的,用起来相当的爽.如果有些场景不满足,需要我们自己去自定义,那要怎么办呢 ...

随机推荐

  1. 产品之我见(1)-女性APP

    我曾下载过几款女性APP,下载的初衷是想要记录.同时预估下一次生理周期开始的时间. 在查找网上测评推荐及个人下载试用了四五款后,我当时留下美柚.大姨吗.Clue这三款.            美柚  ...

  2. [国外] 解决Windows10下google搜索连接不上,但其它网页都能成功登入的问题

    我的电脑突然在学校不能登陆google了,在家可以连接但是非常慢. 在网上搜索发现是由于DNS出了问题,在此记录一下. 可以通过控制面板——网络和Internet——网络和共享中心——点击现在使用的网 ...

  3. Vue的作用域插槽

    一.通常情况下都是父组件传递数据给子组件进行展示的(无法改变子组件的展示方式):而作用域插槽允许子组件通过slot向父组件传递数据,类似React中的“以函数为子组件”,由父组件决定渲染的内容(包含绑 ...

  4. mysql的binlog安全删除的一种方法

    指定过期天数(expire_logs_days) ---适用于单机版mysql!    该参数为全局可动态调整参数,默认值为0,即关闭,取值范围0-99. 1.3.1 参数的查看: mysql> ...

  5. 用命令将本地项目上传到git

    1.(先进入项目文件夹)通过命令 git init 把这个目录变成git可以管理的仓库 git init 2.把文件添加到版本库中,使用命令 git add .添加到暂存区里面去,不要忘记后面的小数点 ...

  6. Kubernetes---Pod重启策略

    PodSpec中有一个restartPolicy 字段,可能的值为Always.OnFailure和Never.默认为Always.restartPolicy 适用于Pod 中的所有容器.restar ...

  7. (八)springMvc 的参数绑定

    参数绑定 将客户端传来的 key/value 数据,绑定到 Controller 参数的过程 : 这一过程发生在调用 处理器适配器 的时候,spring 会去调用 参数绑定 组件,我使用的版本(4.5 ...

  8. Sql Server 收缩日志文件原理及always on 下的实践

    一.准备知识 1.LSN LSN用来标识特定日志在日志文件中位置(详情请见什么是LSN:日志序列号),它由两部分组成:一部分用来标识VLF(虚拟日志文件)的序列号,剩下的用来标识该日志在VLF中的具体 ...

  9. java都13了, 8的新特性你还没不会用吗

    前言 java13都已经来了,很多同学还停留在使用java5的东西.如果在日常开发中没有使用上java8的一些新特性或者不会用.这篇文章对你可能有帮助. lambda表达式 介绍 lambda表达式是 ...

  10. 怎样查看或修改网页的标题title

    网页的标题一般指的是 <title>标签之间的文本节点值, 它会显示在浏览器的标签页上, 我们可以通过 document.title 来查看或修改它: document.title; // ...