Vue自定义指令写法与个人理解


Posted in Javascript onFebruary 09, 2019

什么是Vue指令?

指令是一种可以附加到DOM元素的微命令(tiny commands). 它们通常以"v-"作为前缀, 以方便Vue知道你在使用一种特殊的标记, 从而确保语法的一致性. 如果你需要对HTML元素的低级别(low-level)访问来控制一些行为, 它们通常很有用.

如果你正在使用Vue(或者Angular), 你可能已经很熟悉其中的一些指令, 如: v-if, v-else等等. 我们将从了解一些基础开始, 但是如果你更愿意直接看例子, 请直接往下滚动. 这些例子也能很好的让你理解这些概念.

以下是一些指令的使用方法, 以及对应的例子片段. 这些例子不是规定性的, 它们只是一些用例. 这里的"例子"实际上是"指令".

v-example: 这将实例化一个指令, 但不接受任何参数. 虽然不带参数的指令, 在使用的过程中并不是很灵活, 但是你仍然可以通过这种类型的指令对DOM元素做一些操作.

v-example="value": 这将传递一个值给指令, 并且该指令根据该值计算出要做的操作.

<div v-if="stateExample">I will show up if stateExample is true</div>

v-example="'string'": 这将让你把'string'作为一个表达式.

<p v-html="'<strong>this is an example of a string in some text</strong>'"></p>

v-example:arg="value": 这允许我们传入一个参数给指令. 下面的例子中, 我们绑定到一个类, 将其样式化为一个对象, 单独存储.

<div v-bind:class="someClassObject"></div>

v-example:arg.modifier="value": 这允许我们使用修饰语. 下面的例子中, 允许我们在点击事件时, 调用preventDefault().

<button v-on:submit.prevent="onSubmit"></button>

理解Vue自定义指令

既然我们已经大致过了一遍所有的我们所用过的指令类型方法, 让我们想一想我们如何通过自己编写的自定义指令来实现它们? 使用自定义指令的一个很好的例子是滚动事件, 让我们看看如何实现它.

首先, 最基本的是如何创建一个全局的指令. (是的, 它什么也不做.) 仅仅是创建了一个指令.

Vue.directive('tack');

HTML:

<p v-tack>This element has a directive on it</p>

我们有几个可用的钩子, 每个钩子可以选择一些参数. 钩子如下:

bind: 一旦指令附加到元素时触发
inserted: 一旦元素被添加到父元素时触发
update: 每当元素本身更新(但是子元素还未更新)时触发
componentUpdate: 每单组件和子组件被更新时触发
unbind: 一旦指令被移除时触发

就个人而言, bind和update也许是这五个里面最有用的两个钩子了.
每个钩子都有el, binding, 和vnode参数可用. update和componentUpdated钩子还暴露了oldVnode, 以区分传递的旧值和较新的值.

el, 跟你所期待的一样, 就是所绑定的元素. binding是一个保护传入钩子的参数的对象. 有很多可用的参数, 包括name, value, oldValue, expression, arguments, arg及修饰语. vnode有一个更不寻常的用例, 它可用于你需要直接引用到虚拟DOM中的节点. 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>

毫无疑问, 它完全可以按照我们所希望的工作. 但是它还不够灵活, 如果我们可以传入一个值, 然后直接更新或者重用这个指令就好了. 例如, 我们想为这个元素指定一个值, 表示这个元素离顶部多远(多少个像素), 我们可以这样写(在CODEPEN上查看):

// JS
Vue.directive('tack', {
  bind(el, binding, vnode){
    el.style.position = 'fixed';
    el.style.top = binding.value + 'px';
  }
});

// HTML
<div id="app">
  <p>Scroll down the page</p>
  <p v-tack="70">Stick me 70px from the top of the page</p>
</div>

假设我们想要区分从顶部或者左侧偏移70px, 我们可以通过传递一个参数来做到这一点(在CODEPEN上查看):

// JS
Vue.directive('tack', {
  bind(el, binding, vnode) {
    el.style.position = 'fixed';
    const s = (binding.arg === 'left' ? 'left' : 'top');
    el.style[s] = binding.value + 'px';
  }
});

// HTML
<p v-tack:left="70">I'll now be offset from the left instead of the top</p>

当然, 你可以同时传入不止一个值. 你可以像使用标准指令一样简单的使用自定义指令(在CODEPEN上查看):

// JS
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';
  }
});

// HTML
<p v-tack="{top: '40', left: '100'}">Stick me 40px from the top of the page and 100px from the left of the page</p>

基于我们的自定义指令, 我们可以创建和修改方法, 从而创建更为复杂的自定义指令. 这里, 我们将做一个waypoints-like例子, 用少量的代码实现特定滚动事件触发的动画效果(在CODEPEN上查看):

// JS
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;
    }
  }
});

// HTML
<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>

为了让大家看得更清楚, 在这个代码片段中, 我们尽可能的保证它的简单易读. 在实际的APP中, 你可以构建非常友好的, 并且非常灵活的, 适合整个团队使用的自定义指令.

在实际的构建中, 我会将指令代码放在"main.js"文件中, 该文件位于"src"目录的根目录下(如果你使用的是Vue-cli构建工具), 那么"App.vue"以及组件目录中的所有的.vue文件都可以访问它. 当然, 还要其他方法可以使用它, 但是我发现对于整个应用程序来说, 这是最灵活的实现方式.

以上就是个人对Vue自定义指令的理解,希望对大家有所帮助

Javascript 相关文章推荐
JavaScript创建命名空间(namespace)的最简实现
Dec 11 Javascript
JSON扫盲帖 JSON.as类教程
Feb 16 Javascript
js实现单一html页面两套css切换代码
Apr 11 Javascript
JS实现至少包含字母、大小写数字、字符的密码等级的两种方法
Feb 03 Javascript
javascript组合使用构造函数模式和原型模式实例
Jun 04 Javascript
浅谈javascript中的三种弹窗
Oct 21 Javascript
jQuery插件echarts实现的多柱子柱状图效果示例【附demo源码下载】
Mar 04 Javascript
一篇看懂vuejs的状态管理神器 vuex状态管理模式
Apr 20 Javascript
最基础的vue.js双向绑定操作
Aug 23 Javascript
vue-cli脚手架的安装教程图解
Sep 02 Javascript
Vue源码学习之关于对Array的数据侦听实现
Apr 23 Javascript
详解如何使用nvm管理Node.js多版本
May 06 Javascript
Vue指令指令大全
Feb 09 #Javascript
vue基于两个计算属性实现选中和全选功能示例
Feb 08 #Javascript
vue计算属性get和set用法示例
Feb 08 #Javascript
vue多次循环操作示例
Feb 08 #Javascript
JS散列表碰撞处理、开链法、HashTable散列示例
Feb 08 #Javascript
ES6 对象的新功能与解构赋值介绍
Feb 05 #Javascript
Vue从TodoList中学父子组件通信
Feb 05 #Javascript
You might like
PHP 线程安全与非线程安全版本的区别深入解析
2013/08/06 PHP
Yii中CGridView实现批量删除的方法
2015/12/28 PHP
PHP文件类型检查及fileinfo模块安装使用详解
2019/05/09 PHP
PHP使用PhpSpreadsheet操作Excel实例详解
2020/03/26 PHP
var与Javascript变量隐式声明
2009/09/17 Javascript
js 自动播放的实例代码
2013/11/19 Javascript
将查询条件的input、select清空
2014/01/14 Javascript
js取值中form.all和不加all的区别介绍
2014/01/20 Javascript
初识SmartJS - AOP三剑客
2014/06/08 Javascript
分享一款基于jQuery的视频播放插件
2014/10/09 Javascript
Javascript中3个需要注意的运算符
2015/04/02 Javascript
javascript实现别踩白块儿小游戏程序
2015/11/22 Javascript
jQuery获取table行数并输出单元格内容的实现方法
2016/06/30 Javascript
JS判断一个数是否是水仙花数
2017/06/11 Javascript
Vue学习笔记进阶篇之过渡状态详解
2017/07/14 Javascript
vue计算属性时v-for处理数组时遇到的一个bug问题
2018/01/21 Javascript
Angular7中创建组件/自定义指令/管道的方法实例详解
2019/04/02 Javascript
JS使用正则表达式实现常用的表单验证功能分析
2020/04/30 Javascript
详解Python中列表和元祖的使用方法
2015/04/25 Python
详解Django定时任务模块设计与实践
2019/07/24 Python
python实现微信小程序用户登录、模板推送
2019/08/28 Python
使用pyqt 实现重复打开多个相同界面
2019/12/13 Python
python 解决cv2绘制中文乱码问题
2019/12/23 Python
Anaconda3中的Jupyter notebook添加目录插件的实现
2020/05/18 Python
image-set实现Retina屏幕下图片显示详细介绍
2012/12/24 HTML / CSS
CSS3 box-shadow属性实例详解
2020/06/19 HTML / CSS
css3 transform 3d 使用css3创建动态3d立方体(html5实践)
2013/01/06 HTML / CSS
经贸日语毕业生自荐信
2013/11/03 职场文书
学校十一活动方案
2014/02/01 职场文书
《海底世界》教学反思
2014/04/16 职场文书
2014年学校团委工作总结
2014/12/20 职场文书
创业计划书之校园超市
2019/09/12 职场文书
div与span之间的区别与使用介绍
2021/12/06 HTML / CSS
python opencv将多个图放在一个窗口的实例详解
2022/02/28 Python
Tomcat 与 maven 的安装与使用教程
2022/06/16 Servers
MutationObserver在页面水印实现起到的作用详解
2022/07/07 Javascript