Vue全局指令和私有指令的自定义及使用

一、自定义全局指令

开门见山 举个栗子:

<label>
    搜索
    <input type="text" id="search">
</label>

此时 若要触发这个输入框的获得焦点事件 在原生方法中是这样的:

document.getElementById("search").focus();

而在Vue中 使用自定义指令来实现该效果
指令 就是形如v-model v-text之类的 只不过这些是Vue默认提供的
而自定义指令 就是自定义的(废话

在Vue中 所有的指令使用的时候都以v-开头

自定义一个名为v-focus的自定义指令:
加在标签中

<label>
    搜索
    <input type="text" id="search" v-focus>
</label>

然后 用Vue.directive()来定义全局指令
语法:Vue.directive(指令名称,对象)
第一个参数是指令的名称 在定义的时候 指令前面无需加上v-的前缀 但在调用的时候必须加
第二个参数是个对象 该对象上面有一些指令相关的钩子函数 这些函数可以在特定阶段执行相关的操作

在每个钩子函数中 第一个参数永远是el 其表示被绑定了该指令的元素(element)【当然 参数名可随意取】
它是原生的js的dom对象 因此可以在其上面尽情使用js方法

常用的钩子函数有bind inserted和updated:

  • bind是每当指令绑定到元素上时 会立即执行该bind函数
    只会执行一次 因为一个指令只能绑定到一个元素上一次
  • inserted是当元素插入到DOM中的时候会执行该inserted函数
    其也只会执行一次
  • updated是当DOM节点(VNode组件)更新的时候 会执行该upload函数
    可能会触发多次
Vue.directive("focus",{
            // 钩子函数
            
            // 在bind刚绑定的时候 元素还并没有被放到dom中去 因此此时调用focus()方法没作用 不会生效 因为一个元素只有在插入dom之后才能获取焦点
            bind:function(el)
            {
                // el.focus();
            },
            
            // 元素插入到DOM中的时候会执行该inserted函数
            // 【只会执行一次】
            inserted:function(el)
            {
                el.focus();
            },
            
            // 当DOM节点(VNode组件)更新的时候 会执行该upload函数
            // 【可能会触发多次】
            updated:function(el)
            {
            
            }
        })

除此之外 还有:

  • componentUpdated:指令所在组件的DOM节点(VNode组件)及其子DOM节点(VNode组件)全部更新后调用
  • unbind:指令与元素解绑时调用
    只调用一次

如此 即可实现自定义指令了


当然 样式和行为还是有区别的:
何为样式?样式就是比如设置颜色之类的
而行为 就是比如focus()之类的js行为

拿自定义字体颜色指令举个栗子吧:

Vue.directive("color",{
            bind:function(el)
            {
                el.style.color="aqua";
            }
        })

我们发现样式是可以在bind里设置的
那是因为因为只要样式被解析了 那么显示在页面上就会带有颜色
样式只要通过指令绑定给了元素 不管这个元素有没有被插入到页面中去 这个元素肯定会有了一个内联样式
在那之后 元素肯定会显示到页面中 在这个时候 浏览器的渲染引擎必然会解析样式 然后应用给该元素

但 focus()之类的方法是一个行为 行为必须添加到DOM中才能获得焦点 在bind的时候还只是在内存中 并没有添加到DOM上
在内存中调用的行为 然后再渲染到页面上时 自然是无效的
而insert是到了页面上之后才调用 因此行为会有效

总而言之 和js行为有关的操作最好在inserted里执行 防止js行为不生效
而 和样式相关的操作 通常可以放在bind中执行


在自定义指令中拿到传递的值

在定义的时候 要加上引号 因为传递的是一个字符串
若不加引号 则会识别为是一个变量

<input type="text" id="search" v-color="'blue'">

首先 看一下钩子函数共有哪些参数:

  • el:指令所绑定的元素 可用来直接操作DOM
  • binding:一个对象 包含以下属性:
    name:指令名(不包括v-前缀)
    value:指令的绑定值
    例:在v-my-directive=“1+1"中 绑定值是为2 即:value是经过字符串解析后的结果
    oldValue:指令绑定的前一个值
    仅在update和componentUpdated钩子中可用
    无论值是否改变都可用
    expression:字符串形式的指令表达式
    例:在v-my-directive=“1+1"中 表达式为"1+1” 即:expression是不经过字符串解析后的结果 原原本本的结果
    arg:传给指令的参数
    例:在v-my-directive:foo中 参数为"foo”
    modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }
  • vnode:Vue 编译生成的虚拟节点
  • oldVnode:上一个虚拟节点
    仅在update和componentUpdated钩子中可用

在这里插入图片描述
拿到传递的值
例:

// 自定义设置字体颜色指令
Vue.directive("color",{
    bind:function(el,binding) // 此处的el和binding可任意命名
    {
        console.log(binding.value);
        el.style.color=binding.value;
    }
})

二、自定义私有指令

就像过滤器一样 指令也是不但有共有的指令 也有私有的指令
自定义私有指令其实和自定义私有过滤器类似
都是在Vue实例中的属性对象里进行设置

<div id="app2">
	<h3 v-fontWeight="1000">{{date | dateFormat}}</h3>
</div>
<script>
	var vm2=new Vue({
	            el:'#app2',
	            data:{
	                date:new Date()
	            },
	            methods:{},
	            filters:{},
	            // 自定义私有指令
	            directives:{
	                "fontweight":{
	                    bind:function(el,binding)
	                    {
	                        el.style.fontWeight=binding.value;
	                    }
	                }
	            }
	        })
</script>

三、指令的简写

Vue的自定义指令还支持简写

如果想在bindupdate这两个钩子上进行重复的动作
且不关心其它的钩子函数

那么 可以直接在指令名后面跟上方法

例:

<div id="app2">
	<h3 v-fontWeight="1000" v-fontsize="'50'">{{date | dateFormat}}</h3>
</div>
<script>
	var vm2=new Vue({
	            el:'#app2',
	            data:{
	                date:new Date()
	            },
	            methods:{},
	            filters:{},
	            // 自定义私有指令
	            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";
	                }
	            }
	        })
</script>

发布了200 篇原创文章 · 获赞 11 · 访问量 73万+

猜你喜欢

转载自blog.csdn.net/Piconjo/article/details/105606565