Webcourse/11-Vue基础/01-06.自定义按键修饰符&自定义指令.md
2020-04-19 18:24:43 +08:00

376 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 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;
}
}
```