一、vue中自定义全局按键修饰符?
前面学习了事件修饰符,那么什么是按键修饰符?
在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on
在监听键盘事件时添加按键修饰符:
<input v-on:keyup.enter="submit">
只有在键盘按键按 Enter(回车)键时,才会触发调用 submit() 方法。
你也可以直接将 KeyboardEvent.key
暴露的任意有效按键名转换为 kebab-case 来作为修饰符:
<input v-on:keyup.page-down="onPageDown">
在上述示例中,处理函数只会在 $event.key
等于 PageDown
时被调用。
接下来了解一下 按键码
keyCode
的事件用法已经被废弃了并可能不会被最新的浏览器支持。
使用 keyCode
attribute 也是允许的:
<input v-on:keyup.13="submit">
为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名:
.enter
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right
有一些按键 (.esc
以及所有的方向键) 在 IE9 中有不同的 key
值, 如果你想支持 IE9,这些内置的别名应该是首选。
如果上面的常用按键都不是想要的,如果想要自定义按键修饰符别名怎么办呢?
此处 113 是 f2 按键对应的键码值
// 自定义全局按键修饰符
Vue.config.keyCodes.f2 = 113
使用的时候:
<input type="text" v-model="name" @keyup.f2="add">
常见键盘按键对应键码值大全可以参考这个链接:https://www.cnblogs.com/wuhua1/p/6686237.html
1.x中自定义键盘修饰符【了解即可】
Vue.directive('on').keyCodes.f2 = 113;
2.x中自定义键盘修饰符
-
通过`Vue.config.keyCodes.名称 = 按键值`来自定义案件修饰符的别名:
Vue.config.keyCodes.f2 = 113;
- 使用自定义的按键修饰符:
<input type="text" v-model="name" @keyup.f2="add">
二、自定义全局过滤器
所谓的全局过滤器,就是所有的VM实例都共享的。
Vue.filter('myFilter', function (data) {
return data + '123'
})
怎么调用?
<h3>{{ dt | myFilter}}</h3>
// data 中 dt: new Date()
过滤器调用时候的格式 {{ name | 过滤器的名称 }} ,其中 | 符号,我们称为 管道符
// 过滤器的定义语法
// Vue.filter('过滤器的名称', function(){})
// 过滤器中的 function ,第一个参数,已经被规定死了,永远都是 过滤器 管道符前面 传递过来的数据
/*
Vue.filter('过滤器的名称', function (参数) {
return 要做的操作
})
*/
过滤器中的 function 可以设置默认参数值,这里 pattern 默认为空值
Vue.filter('dateFormat', function (dateStr, pattern = "") {
// do something ...
})
三、定义私有过滤器
有了全局过滤器,当然也可以有私有(局部)过滤器,所谓私有就是只能在 当前 VM 对象所控制的 View 区域进行使用
// 如何自定义一个私有的过滤器(局部)
var vm2 = new Vue({
el: '#app2',
data: {},
methods: {},
filters: {
dateFormat: function (data) {
return data + '123'
}
}
})
私有过滤器只需要定义一个 filters 字段,在里面设置过滤器名称然后定义方法即可。
那么当全局过滤器和局部过滤器同时存在且同名时,调用的时候调用的是全局的过滤器还是局部的呢?
答:当有局部和全局两个名称相同的过滤器时候,会以就近原则进行调用,即:局部过滤器优先于全局过滤器被调用!
四、自定义全局指令
前面学过很多关于 vue 的指令:v-cloak, v-text, v-html, v-on, v-bind, v-for, v-if, v-show, v-model等等
有没有发现 vue 中的指令都是以 v- 开头
所以有一个约定就是 Vue中所有的指令,在调用的时候,都以 v- 开头
我们要定义全局指令的时候需要使用到 Vue.directive()
其中:
- 参数1 : 指令的名称,注意,在定义的时候,指令的名称前面,不需要加 v- 前缀,(但是在调用的时候,必须在指令名称前 加上 v- 前缀来进行调用)
- 参数2: 是一个对象,这个对象身上,有一些指令相关的函数,这些函数可以在特定的阶段,执行相关的操作
假设我们进入某个页面,要使某个输入文本框获得焦点,通常用 js 我们的操作是:
document.getElementById('search').focus()
但是在 vue 中,我们可以通过自定义一个 自动获取焦点 的指令来实现
先上代码:
Vue.directive('focus', {
bind: function (el) {
},
inserted: function (el) {
el.focus()
},
updated: function (el) {
}
})
看不懂代码?那么在这里就要了解一下 钩子函数 这个东西了(参考 vue 官网教程)
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
-
bind
:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。 -
inserted
:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。 -
update
:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
-
componentUpdated
:指令所在组件的 VNode 及其子 VNode 全部更新后调用。 -
unbind
:只调用一次,指令与元素解绑时调用。
接下来我们来看一下钩子函数的参数 (即 el
、binding
、vnode
和 oldVnode
)。
钩子函数参数
指令钩子函数会被传入以下参数:
el
:指令所绑定的元素,可以用来直接操作 DOM 。binding
:一个对象,包含以下属性:name
:指令名,不包括v-
前缀。value
:指令的绑定值,例如:v-my-directive="1 + 1"
中,绑定值为2
。oldValue
:指令绑定的前一个值,仅在update
和componentUpdated
钩子中可用。无论值是否改变都可用。expression
:字符串形式的指令表达式。例如v-my-directive="1 + 1"
中,表达式为"1 + 1"
。arg
:传给指令的参数,可选。例如v-my-directive:foo
中,参数为"foo"
。modifiers
:一个包含修饰符的对象。例如:v-my-directive.foo.bar
中,修饰符对象为{ foo: true, bar: true }
。
vnode
:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。oldVnode
:上一个虚拟节点,仅在update
和componentUpdated
钩子中可用。
除了 el
之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的 dataset
来进行。
回到代码上,为什么 el.focus() 放在了 inserted 函数中?
-
每当指令绑定到元素上的时候,会立即执行这个 bind 函数,只执行一次。在元素 刚绑定了指令的时候,还没有 插入到 DOM中去,这时候,调用 focus 方法没有作用
-
一个元素,只有插入DOM之后,才能获取焦点(inserted 表示元素 插入到DOM中的时候,会执行 inserted 函数【触发1次】)
-
和JS行为有关的操作,最好在 inserted 中去执行
自定义一个 设置字体颜色 的指令,怎么做?
Vue.directive('color', {
bind: function (el, binding) {
// el.style.color = 'red'
console.log(binding.name)
console.log(binding.value)
console.log(binding.expression)
el.style.color = binding.value
}
})
调用:
<h3 v-color="'green'">哈哈</h3>
看看控制台都输出了什么:
那么在这里为什么颜色的设置写在了 bind 函数中呢?
-
样式,只要通过指令绑定给了元素,不管这个元素有没有被插入到页面中去,这个元素肯定有了一个内联的样式
-
将来元素肯定会显示到页面中,这时候,浏览器的渲染引擎必然会解析样式,应用给这个元素
-
和样式相关的操作,一般都可以在 bind 执行
五、自定义私有指令
和私有过滤器的定义类似,也是加一个字段,这个字段就是 directives
var vm2 = new Vue({
el: '#app2',
data: {},
methods: {},
directives: { // 自定义私有指令
'fontweight': { // 设置字体粗细的
bind: function (el, binding) {
el.style.fontWeight = binding.value
}
},
'fontsize': function (el, binding) { // 注意:这个 function 等同于 把 代码写到了 bind 和 update 中去
el.style.fontSize = parseInt(binding.value) + 'px'
}
}
})
注意这里用了两种不同的写法
调用的时候:
<h3 v-color="'pink'" v-fontweight="900" v-fontsize="50">哈哈</h3>
关于同名调用的优先级和过滤器中一样,就近原则。