自定义按键修饰符&自定义指令

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。

核心代码如下:

    <input type="text" v-model="formData.name" @keyup.enter="addData">

注意,如果写成@keyup="addData",效果却是:只要键盘的任何键位打了字(还没来得及按enter键),就会执行addData()方法,这种效果显然不是我们想要的。所以要加上修饰符.enter,表示只针对enter键。

自定义的按键修饰符

如果我们直接在代码的<input>标签里写@keyup.f2="addData",那么,按住「F2键」后,是没有效果的,因为「F2键」不是内置的按键修饰符(如果F2不能验证,你可以试一下F7)。

我们知道,每个按键都有一个键盘码。参考链接:

通过查阅,我们知道了「F2键」的键盘码为113,那代码可以这样写:(按住F2键后,执行 addData 方法)

    <input type="text" v-model="formData.name" @keyup.113="addData">

虽然键盘码很全,但是不好记呀。于是,接下来,我们给键盘码定义别名。

自定义全局按键修饰符

    //自定义全局按键修饰符
    Vue.config.keyCodes.f2 = 113;

上方代码的书写位置,与自定义全局过滤器的位置,是并列的。

然后,我们就可以使用键盘码的别名了。

自定义全局指令

自定义全局指令的举例1

举例1:让指定文本框自动获取焦点

如果我们想实现这个例子,原生js的写法是:

    //原生js写法:网页一打开,就让指定的输入框自动获取焦点
    document.getElementById('search').focus()

代码的位置:


image

但我们不建议这样做。我们可以通过Vue中的自定义指令来实现这个例子。步骤如下。

(1)使用Vue.directive()自定义全局指令:

    //自定义全局指令 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中去。

由此可以看看出:bindinsertedupdated这三个钩子函数的执行时机不同,且执行的次数有区别。
(2)在指定的文本框上加``:

<input type="text" id="search" v-model="keywords" v-focus>

完整版代码如下:

<!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元素设置样式:

<!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元素中传参。一起来看看。

代码如下:【荐】

<!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'",这里面写的是字符串常量;如果去掉单引号,就成了变量,不是我们想要的。

自定义全局指令的简写形式

在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。比如上面的代码中,我们可以写成简写形式:

        Vue.directive('color', function (el, binding) { //注意,这个function等同于把代码写到了 bind 和 update 中去
            el.style.color = binding.value
        })

自定义私有指令

自定义私有指令:在某一个 vue 对象内部自定义的指令称之为私有指令。这种指令只有在当前vue对象的el指定的监管区域有用。

代码举例:(设置文字的font-weight属性)

<!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>

注意, el.style.fontWeight设置属性值,至少要600,否则看不到加粗的效果。

自定义私有指令的简写形式

在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。比如上面的代码中,我们可以写成简写形式:

            //自定义私有指令(简写形式)
            directives: {
                'fontweight': function (el, binding) { //注意,这个function等同于把代码写到了 bind 和 update 中去
                    el.style.fontWeight = binding.value;
                }
            }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容