mirror of
https://github.com/qianguyihao/Web.git
synced 2024-11-01 13:34:46 +08:00
386 lines
13 KiB
Markdown
386 lines
13 KiB
Markdown
|
---
|
|||
|
title: 07-自定义按键修饰符&自定义指令
|
|||
|
publish: true
|
|||
|
---
|
|||
|
|
|||
|
<ArticleTopAd></ArticleTopAd>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
## v-on的按键修饰符
|
|||
|
|
|||
|
### Vue 内置的按键修饰符
|
|||
|
|
|||
|
通俗一点讲,指的是:监听键盘输入的事件。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符。如下:
|
|||
|
|
|||
|
Vue内置的按键修饰符:
|
|||
|
|
|||
|
```
|
|||
|
.enter
|
|||
|
.tab
|
|||
|
.delete (捕获 “删除” 和 “退格” 键)
|
|||
|
.esc
|
|||
|
.space
|
|||
|
.up
|
|||
|
.down
|
|||
|
.left
|
|||
|
.right
|
|||
|
1.0.8+版本:支持单字母的按键别名。
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
比如说,`keyup`指的是:键盘(任何键位)抬起时的监听事件。`.enter`指的是:按enter键的按键修饰符。我们把这两个结合起来看看。
|
|||
|
|
|||
|
**`@keyup.enter`举例**:按enter键后的监听事件
|
|||
|
|
|||
|
`@keyup.enter="addData"`表示:按住enter键后,执行addData()方法。**全称**是`v-on:key.enter="addData"`。
|
|||
|
|
|||
|
我们还是拿`01-04`这篇文章中的列表功能来举例。之前是点击“添加”按钮后,列表中会添加一个item。现在要求:在**输入框**中按enter键后,也能添加一个item。
|
|||
|
|
|||
|
核心代码如下:
|
|||
|
|
|||
|
```html
|
|||
|
<input type="text" v-model="formData.name" @keyup.enter="addData">
|
|||
|
```
|
|||
|
|
|||
|
注意,如果写成`@keyup="addData"`,效果却是:只要键盘的任何键位打了字(还没来得及按enter键),就会执行addData()方法,这种效果显然不是我们想要的。所以要加上修饰符`.enter`,表示只针对enter键。
|
|||
|
|
|||
|
### 自定义的按键修饰符
|
|||
|
|
|||
|
如果我们直接在代码的`<input>`标签里写`@keyup.f2="addData"`,那么,按住「F2键」后,是没有效果的,因为「F2键」不是内置的按键修饰符(如果F2不能验证,你可以试一下F7)。
|
|||
|
|
|||
|
我们知道,每个按键都有一个键盘码。参考链接:
|
|||
|
|
|||
|
- [js 里面的键盘事件对应的键码](http://www.cnblogs.com/wuhua1/p/6686237.html)
|
|||
|
|
|||
|
通过查阅,我们知道了「F2键」的键盘码为`113`,那代码可以这样写:(按住F2键后,执行 addData 方法)
|
|||
|
|
|||
|
```html
|
|||
|
<input type="text" v-model="formData.name" @keyup.113="addData">
|
|||
|
```
|
|||
|
|
|||
|
虽然键盘码很全,但是不好记呀。于是,接下来,我们给键盘码定义别名。
|
|||
|
|
|||
|
**自定义全局按键修饰符**:
|
|||
|
|
|||
|
```
|
|||
|
//自定义全局按键修饰符
|
|||
|
Vue.config.keyCodes.f2 = 113;
|
|||
|
```
|
|||
|
|
|||
|
上方代码的书写位置,与自定义全局过滤器的位置,是并列的。
|
|||
|
|
|||
|
然后,我们就可以使用键盘码的别名了。
|
|||
|
|
|||
|
## 自定义全局指令
|
|||
|
|
|||
|
### 自定义全局指令的举例1
|
|||
|
|
|||
|
**举例1**:让指定文本框自动获取焦点
|
|||
|
|
|||
|
如果我们想实现这个例子,原生js的写法是:
|
|||
|
|
|||
|
```javascript
|
|||
|
//原生js写法:网页一打开,就让指定的输入框自动获取焦点
|
|||
|
document.getElementById('search').focus()
|
|||
|
```
|
|||
|
|
|||
|
代码的位置:
|
|||
|
|
|||
|
![](http://img.smyhvae.com/20180527_2340.png)
|
|||
|
|
|||
|
但我们不建议这样做。我们可以通过Vue中的自定义指令来实现这个例子。步骤如下。
|
|||
|
|
|||
|
(1)使用`Vue.directive()`自定义全局指令:
|
|||
|
|
|||
|
```javascript
|
|||
|
|
|||
|
//自定义全局指令 v-focus:让文本框自动获取焦点
|
|||
|
//参数1:指令的名称。注意,在定义的时候,指令的名称前面,不需要加 v- 前缀;但是:在`调用`的时候,必须在指令名称前 加上 v- 前缀
|
|||
|
//参数2:是一个对象,这个对象身上,有一些指令相关的函数,这些函数可以在特定的阶段,执行相关的操作
|
|||
|
Vue.directive('focus', {
|
|||
|
//在每个函数中,第一个参数,永远是 el ,表示 被绑定了指令的那个元素,这个 el 参数,是一个原生的JS对象(DOM对象)
|
|||
|
bind: function (el) { // 每当指令绑定到元素上的时候,会立即执行这个 bind 函数,【只执行一次】
|
|||
|
// 在元素 刚绑定了指令的时候,还没有 插入到 DOM中去,这时候,调用 focus 方法没有作用
|
|||
|
// 因为,一个元素,只有插入DOM之后,才能获取焦点
|
|||
|
// el.focus()
|
|||
|
},
|
|||
|
inserted: function (el) { // inserted 表示元素 插入到DOM中的时候,会执行 inserted 函数【触发1次】
|
|||
|
el.focus()
|
|||
|
// 和JS行为有关的操作,最好在 inserted 中去执行,放置 JS行为不生效
|
|||
|
},
|
|||
|
updated: function (el) { // 当VNode更新的时候,会执行 updated, 【可能会触发多次】
|
|||
|
|
|||
|
}
|
|||
|
})
|
|||
|
```
|
|||
|
|
|||
|
上方的代码中,如果我们把`el.focus()`这行代码写在`bind`方法里,是没有效果的(但不会报错)。没有效果是因为,在执行到`bind`方法的时候,元素还没有插入到dom中去。
|
|||
|
|
|||
|
由此可以看看出:`bind`、`inserted`、`updated`这三个钩子函数的执行时机不同,且执行的次数有区别。
|
|||
|
|
|||
|
(2)在指定的文本框上加``:
|
|||
|
|
|||
|
```html
|
|||
|
<input type="text" id="search" v-model="keywords" v-focus>
|
|||
|
```
|
|||
|
|
|||
|
完整版代码如下:
|
|||
|
|
|||
|
```html
|
|||
|
<!DOCTYPE html>
|
|||
|
<html lang="en">
|
|||
|
|
|||
|
<head>
|
|||
|
<meta charset="UTF-8">
|
|||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|||
|
<title>Document</title>
|
|||
|
<script src="vue2.5.16.js"></script>
|
|||
|
</head>
|
|||
|
|
|||
|
<body>
|
|||
|
|
|||
|
<div id="app">
|
|||
|
搜索框:
|
|||
|
<input type="text" id="search" v-model="name" v-focus>
|
|||
|
</div>
|
|||
|
|
|||
|
<script>
|
|||
|
|
|||
|
//自定义全局指令 v-focus,让文本框自动获取焦点
|
|||
|
//参数1:指令的名称。注意,在定义的时候,指令的名称前面,不需要加 v- 前缀;但是:在`调用`的时候,必须在指令名称前 加上 v- 前缀
|
|||
|
//参数2:是一个对象,这个对象身上,有一些指令相关的函数,这些函数可以在特定的阶段,执行相关的操作
|
|||
|
Vue.directive('focus', {
|
|||
|
//在每个函数中,第一个参数,永远是 el ,表示 被绑定了指令的那个元素,这个 el 参数,是一个原生的JS对象(DOM对象)
|
|||
|
bind: function (el) { // 每当指令绑定到元素上的时候,会立即执行这个 bind 函数,【只执行一次】
|
|||
|
// 在元素 刚绑定了指令的时候,还没有 插入到 DOM中去,这时候,调用 focus 方法没有作用
|
|||
|
// 因为,一个元素,只有插入DOM之后,才能获取焦点
|
|||
|
// el.focus()
|
|||
|
},
|
|||
|
inserted: function (el) { // inserted 表示元素 插入到DOM中的时候,会执行 inserted 函数【触发1次】
|
|||
|
el.focus()
|
|||
|
// 和JS行为有关的操作,最好在 inserted 中去执行,防止 JS行为不生效
|
|||
|
},
|
|||
|
updated: function (el) { // 当VNode更新的时候,会执行 updated, 【可能会触发多次】
|
|||
|
}
|
|||
|
})
|
|||
|
|
|||
|
new Vue({
|
|||
|
el: '#app',
|
|||
|
data: {
|
|||
|
name: 'smyhvae'
|
|||
|
}
|
|||
|
})
|
|||
|
</script>
|
|||
|
</body>
|
|||
|
|
|||
|
</html>
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
### 自定义全局指令:使用钩子函数的第二个binding参数拿到传递的值
|
|||
|
|
|||
|
**举例2**:设置DOM元素的color样式
|
|||
|
|
|||
|
|
|||
|
参考举例1中的写法,我们可能会这样给DOM元素设置样式:
|
|||
|
|
|||
|
```html
|
|||
|
<!DOCTYPE html>
|
|||
|
<html lang="en">
|
|||
|
|
|||
|
<head>
|
|||
|
<meta charset="UTF-8">
|
|||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|||
|
<title>Document</title>
|
|||
|
<script src="vue2.5.16.js"></script>
|
|||
|
</head>
|
|||
|
|
|||
|
<body>
|
|||
|
|
|||
|
<div id="app">
|
|||
|
搜索框:
|
|||
|
<input type="text" id="search" v-model="name" v-color>
|
|||
|
</div>
|
|||
|
|
|||
|
<script>
|
|||
|
|
|||
|
//自定义全局指令 v-color:设置DOM元素的color属性
|
|||
|
Vue.directive('color', {
|
|||
|
bind: function (el) { // 每当指令绑定到元素上的时候,会立即执行这个 bind 函数,【只执行一次】
|
|||
|
el.style.color = 'red';
|
|||
|
},
|
|||
|
inserted: function (el) { // inserted 表示元素 插入到DOM中的时候,会执行 inserted 函数【触发1次】
|
|||
|
// 和JS行为有关的操作,最好在 inserted 中去执行,防止 JS行为不生效
|
|||
|
//el.focus()
|
|||
|
},
|
|||
|
updated: function (el) { // 当VNode更新的时候,会执行 updated, 【可能会触发多次】
|
|||
|
}
|
|||
|
})
|
|||
|
|
|||
|
new Vue({
|
|||
|
el: '#app',
|
|||
|
data: {
|
|||
|
name: ''
|
|||
|
}
|
|||
|
})
|
|||
|
</script>
|
|||
|
</body>
|
|||
|
|
|||
|
</html>
|
|||
|
```
|
|||
|
|
|||
|
如上方代码所示,我们自定义了一个指令`v-color`,然后在`input`标签中用上了这个指令,就给元素设置了color属性。但是这个代码有个弊端是:color的属性值在定义指令的时候,被写死了。如何完善呢?我们可以在DOM元素中传参。一起来看看。
|
|||
|
|
|||
|
代码如下:【荐】
|
|||
|
|
|||
|
```html
|
|||
|
<!DOCTYPE html>
|
|||
|
<html lang="en">
|
|||
|
|
|||
|
<head>
|
|||
|
<meta charset="UTF-8">
|
|||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|||
|
<title>Document</title>
|
|||
|
<script src="vue2.5.16.js"></script>
|
|||
|
</head>
|
|||
|
|
|||
|
<body>
|
|||
|
|
|||
|
<div id="app">
|
|||
|
搜索框1:
|
|||
|
<input type="text" id="search" v-model="name" v-color="'green'">
|
|||
|
</div>
|
|||
|
|
|||
|
<script>
|
|||
|
|
|||
|
//自定义全局指令 v-color:设置DOM元素的color属性
|
|||
|
Vue.directive('color', {
|
|||
|
// 样式,只要通过指令绑定给了元素,不管这个元素有没有被插入到页面中去,这个元素肯定有了一个内联的样式
|
|||
|
// 将来元素肯定会显示到页面中,这时候,浏览器的渲染引擎必然会解析样式,应用给这个元素
|
|||
|
// 意思是说,我们可以把样式的代码写到bind中去(即使这个时候,dom元素还没有被创建)
|
|||
|
bind: function (el, binding) { // 每当指令绑定到元素上的时候,会立即执行这个 bind 函数,【只执行一次】
|
|||
|
|
|||
|
console.log(binding.name); //打印结果:color
|
|||
|
console.log(binding.value); //打印结果:green
|
|||
|
console.log(binding.expression); //'green'
|
|||
|
|
|||
|
el.style.color = binding.value// 通过bining拿到v-color中传递过来的值
|
|||
|
|
|||
|
},
|
|||
|
inserted: function (el) { // inserted 表示元素 插入到DOM中的时候,会执行 inserted 函数【触发1次】
|
|||
|
// 和JS行为有关的操作,最好在 inserted 中去执行,防止 JS行为不生效
|
|||
|
//el.focus()
|
|||
|
},
|
|||
|
updated: function (el) { // 当VNode更新的时候,会执行 updated, 【可能会触发多次】
|
|||
|
}
|
|||
|
})
|
|||
|
|
|||
|
new Vue({
|
|||
|
el: '#app',
|
|||
|
data: {
|
|||
|
name: 'smyhvae'
|
|||
|
}
|
|||
|
})
|
|||
|
</script>
|
|||
|
</body>
|
|||
|
|
|||
|
</html>
|
|||
|
```
|
|||
|
|
|||
|
上方代码中,bind方法里传递的第二个参数`binding`,可以拿到DOM元素中`v-color`里填的值。注意,`v-color="'green'"`,这里面写的是字符串常量;如果去掉单引号,就成了变量,不是我们想要的。
|
|||
|
|
|||
|
效果:
|
|||
|
|
|||
|
![](http://img.smyhvae.com/20180610_1323.png)
|
|||
|
|
|||
|
**自定义全局指令的简写形式**:
|
|||
|
|
|||
|
|
|||
|
在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。比如上面的代码中,我们可以写成简写形式:
|
|||
|
|
|||
|
```javascript
|
|||
|
Vue.directive('color', function (el, binding) { //注意,这个function等同于把代码写到了 bind 和 update 中去
|
|||
|
el.style.color = binding.value
|
|||
|
})
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
## 自定义私有指令
|
|||
|
|
|||
|
**自定义私有指令**:在某一个 vue 对象内部自定义的指令称之为私有指令。这种指令只有在当前vue对象的el指定的监管区域有用。
|
|||
|
|
|||
|
代码举例:(设置文字的font-weight属性)
|
|||
|
|
|||
|
```html
|
|||
|
<!DOCTYPE html>
|
|||
|
<html lang="en">
|
|||
|
|
|||
|
<head>
|
|||
|
<meta charset="UTF-8">
|
|||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|||
|
<title>Document</title>
|
|||
|
<script src="vue2.5.16.js"></script>
|
|||
|
</head>
|
|||
|
|
|||
|
<body>
|
|||
|
|
|||
|
<div id="app">
|
|||
|
<span v-fontweight="600">生命壹号</span>
|
|||
|
</div>
|
|||
|
<script>
|
|||
|
|
|||
|
new Vue({
|
|||
|
el: '#app',
|
|||
|
data: {
|
|||
|
name: 'smyhvae'
|
|||
|
},
|
|||
|
//自定义私有指令
|
|||
|
directives: {
|
|||
|
'fontweight': {
|
|||
|
bind: function (el, binding) {
|
|||
|
el.style.fontWeight = binding.value;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
})
|
|||
|
</script>
|
|||
|
</body>
|
|||
|
|
|||
|
</html>
|
|||
|
```
|
|||
|
|
|||
|
效果:
|
|||
|
|
|||
|
![](http://img.smyhvae.com/20180610_1400.png)
|
|||
|
|
|||
|
注意, el.style.fontWeight设置属性值,至少要600,否则看不到加粗的效果。
|
|||
|
|
|||
|
**自定义私有指令的简写形式**:
|
|||
|
|
|||
|
在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。比如上面的代码中,我们可以写成简写形式:
|
|||
|
|
|||
|
```
|
|||
|
//自定义私有指令(简写形式)
|
|||
|
directives: {
|
|||
|
'fontweight': function (el, binding) { //注意,这个function等同于把代码写到了 bind 和 update 中去
|
|||
|
el.style.fontWeight = binding.value;
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|