(六)Vue - 自定义指令
- 自定义指令的介绍
- 自定义全局指令及钩子函数
- 钩子函数参数
- 自定义局部指令
- 函数的简写
- 自定义键盘修饰符
自定义指令的介绍
前面文章中讲解了一些Vue自带指令的使用,
如果Vue自带的指令不满足于我们的需求呢?
这篇文章我们学习如何自定义自己想要的指令来满足我们的项目需要。
关于指令,我们可以总结下面几点:
指令是写在 HTML 属性地方的.<input v-model='name' type='text' />
指令都是以 v- 开头的.
指令表达式的右边一般也可以跟值,例如v-model='name'
同Vue中的过滤器,自定义指令也分为全局和局部。
举个聚焦输入框的例子:
需求:
- 当页面加载完成时,输入框自动获取焦点
- 并且可以在body的input标签中设置输入字符的颜色
自定义全局指令及钩子函数
针对需求①,我们用自定义全局指令来说明
<body>
<div id="app">
<input v-focus/>
</div>
<script>
// 1.这里使用Vue.directive()注册一个全局的指令 `v-focus`
// 2.其中参数1为指令的名称,这里指令的名称不需要加v-前缀,但是在使用时,必须加上v-前缀来调用
// 3.参数2是一个对象,这个对象上会有一些指令相关的函数,这些函数再特定阶段被调用
Vue.directive('focus', {
bind:function(el){ //每当指令绑定到元素上的时候,会立即调用这个bind函数,只执行一次,这里可进行一次性的初始化设置
},
inserted: function (el) { //当元素插入到DOM中的时候,会执行一次inserted函数,只会执行一次
// 每个函数的第一个参数是被绑定了指令的el元素,是一个原生js对象
// 这里因为元素需要插入到dom之后才能获取焦点,所以el.focus()方法写在inserted中
el.focus()
},
update: function(el){ //所在组件的 VNode 更新时调用,会触发多次
},
componentUpdated:function(){//指令所在组件的 VNode 及其子 VNode 全部更新后调用。
},
unbind: function(){//只调用一次,指令与元素解绑时调用。
}
})
var vm = new Vue({
el: '#app',
data: {
msg: '我是一段文字,很长很长的文字,中文字'
}
});
</script>
</body>
上面代码执行后,当初次进入界面,此输入框自动获取焦点
针对上面的例子,我们自定义了一个全局指令,同时再代码中以注释的形式说明了自定义指令的5个可选钩子函数,接下来借用一下官方文档来看一下钩子函数的参数 (即 el、binding、vnode 和 oldVnode)。
钩子函数参数
用样例来说明这些参数更容易理解
<div id="hook-arguments-example" v-demo:foo.a.b="message"></div>
Vue.directive('demo', {
bind: function (el, binding, vnode) {
var s = JSON.stringify
el.innerHTML =
'name: ' + s(binding.name) + '<br>' +
'value: ' + s(binding.value) + '<br>' +
'expression: ' + s(binding.expression) + '<br>' +
'argument: ' + s(binding.arg) + '<br>' +
'modifiers: ' + s(binding.modifiers) + '<br>' +
'vnode keys: ' + Object.keys(vnode).join(', ')
}
})
new Vue({
el: '#hook-arguments-example',
data: {
message: 'hello!'
}
})
动态指令参数
指令的参数可以是动态的。例如,在 v-mydirective:[argument]=“value” 中,argument 参数可以根据组件实例数据进行更新!这使得自定义指令可以在应用中被灵活使用。
例如需求要创建一个把元素固定在某一方向指定像素的指令
这时使用动态参数就可以非常方便地根据每个组件实例来进行更新。
<div id="dynamicexample">
<h3>Scroll down inside this section ↓</h3>
<p v-pin:[direction]="200">I am pinned onto the page at 200px to the left.</p>
</div>
Vue.directive('pin', {
bind: function (el, binding, vnode) {
el.style.position = 'fixed'
var s = (binding.arg == 'left' ? 'left' : 'top')
el.style[s] = binding.value + 'px'
}
})
new Vue({
el: '#dynamicexample',
data: function () {
return {
direction: 'left'
}
}
})
自定义局部指令
了解了自定义全局指令和钩子函数及函数参数,下面使用自定义局部指令来完成需求②
<body>
<div id="app">
<!-- v-color的参数使用单引号,如果不用单引号,则会拿red去data中找 -->
<input v-focus v-color="'red'"/>
</div>
<script>
Vue.directive('focus', {
inserted: function (el) { //当元素插入到DOM中的时候,会执行一次inserted函数,只会执行一次
// 每个函数的第一个参数是被绑定了指令的el元素,是一个原生js对象
// 这里因为元素需要插入到dom之后才能获取焦点,所以el.focus()方法写在inserted中
el.focus()
}
})
var vm = new Vue({
el: '#app',
data: {
msg: '我是一段文字,很长很长的文字,中文字'
},
directives: {
//定义一个名称为color的局部指令,钩子函数和函数参数同定义全局指令
color: {
// 样式只要通过指令绑定给了元素,成为内联样式,不需要管这个元素是否被插入到dom中
// 所以这里使用bind的钩子函数即可,和样式相关的操作一般在此钩子函数调用
bind: function(el,binding){
el.style.color = binding.value;
}
}
}
});
注意:
如果指令需要多个值,可以传入一个 JavaScript 对象字面量。记住,指令函数能够接受所有合法的 JavaScript 表达式。
<div v-demo="{ color: 'white', text: 'hello!' }"></div>
Vue.directive('demo', function (el, binding) {
console.log(binding.value.color) // => "white"
console.log(binding.value.text) // => "hello!"
})
函数的简写
在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。比如这样写:
Vue.directive('color', function (el, binding) {
el.style.color = binding.value
})
自定义键盘修饰符
通过前面的文章我们已经知道了v-on指令
工作中经常需要监听键盘事件时,我们需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:
<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
你可以直接将 KeyboardEvent.key 暴露的任意有效按键名 来作为修饰符。
//处理函数只会在 $event.key 等于 PageDown 时被调用
<input v-on:keyup.page-down="onPageDown">
直接使用 keyCode 也是允许的:
<input v-on:keyup.13="submit">
为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名:
Vue没有提供的其它按键码,我们也可以通过全局 config.keyCodes 对象自定义按键修饰符别名:
// 可以使用 `v-on:keyup.f1`
Vue.config.keyCodes.f1 = 112