Vue自定义指令写法与个人理解
什么是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自定义指令的理解,希望对大家有所帮助
推荐阅读
-
Vue.js每天必学之指令系统与自定义指令
-
Vue自定义指令写法与个人理解
-
Vue组件的使用及个人理解与介绍
-
vue.js内部自定义指令与全局自定义指令的实现详解(利用directive)
-
Vue.js自定义指令的用法与实例解析
-
浅谈vue中关于checkbox数据绑定v-model指令的个人理解
-
vue.js响应式原理解析与实现—实现v-model与{{}}指令
-
vue自定义指令限制输入框输入值的步骤与完整代码
-
个人笔记 -- Axios封装原理、console.log()和console.dir()的区别、开发环境解决跨域问题、Vue设置全局自定义指令、cookies和localstorage区别
-
Vue.js每天必学之指令系统与自定义指令