五、指令(4)

本章概要

  • 自定义指令
    • 钩子函数
    • 动态指令参数
    • 函数简写
    • 对象字面量

5.2 自定义指令

5.2.1 自定义指令的注册

自定义指令需要注册后才能使用,Vue 提供了两种注册方式:全局注册和本地注册。
全局注册使用应用程序实例的 directive() 方法注册一个全局自定义指令,该方法接受两个参数,第一个参数是指令的名字;第二个参数是一个定义对象或函数对象,将指令要实现的功能在这个对象中定义。
语法形式如下:

app.directive(name,[definition])

例如,要编写一个让元素自动获取焦点的全局指令。如下:

const app = Vue.createApp({});
app.directive('focus',{
  //...
})

本地注册是在组件实例的选项对象中使用 directive 选项进行注册。如下:

directives:{
  focus:{
    //指令定义
    mounted(el) {
      el.focus;
    }
  }
}

然后在模板中就可以在任何元素上使用 v-focus 指令了,如下:

<input v-focus>

5.2.2 钩子函数

自定义指令的功能是在定义对象中实现的,而定义对象则是由钩子函数组成的,Vue 提供了下面几个钩子函数,这些钩子函数都是可选的。

  • beforeMount :当指令第一次绑定到元素并且在挂载父组件之前调用。指令如果需要一些一次性的初始化设置,可以放到这个钩子函数中
  • mounted:在挂载绑定元素的父组件时调用
  • beforeUpdate:指令所在组件的 VNode 更新之前调用
  • updated:指令所在组件的 VNode 及其子组件的 Vnode 全部更新后调用
  • beforeUnmount:在卸载绑定元素的父组件之前调用
  • unmounted:只调用一次,指令与元素解绑且父组件已卸载时调用

根据指令要实现功能的不同,选择相应的钩子函数来编写代码。例如 5.2.1小节中的 v-focus 指令,我们希望在绑定元素被挂载到 DOM 时就自动获得焦点,那么就可以在 mounted 钩子函数中编写自动聚焦的代码。如下:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<body>
		<div id="app">
			<input v-focus>
		</div>
	
		<script src="https://unpkg.com/vue@next"></script>
		<script>
		    const app = Vue.createApp({});
			// 注册一个全局自定义指令
			app.directive('focus', {
			  // 当绑定元素被挂载到DOM中时
			  mounted(el) {
			    // 聚焦元素
			    el.focus()
			  }
			})
			app.mount('#app')
		</script>
	</body>
</html>

浏览器中的显示效果如下:
在这里插入图片描述

指令的钩子函数可以带有一些参数,例5-17中 mounted 函数的 el 参数就是其中之一,这些参数如下:

  • el:指令所绑定的元素,可以用来直接操作 DOM
  • binding:一个对象,包含以下属性
    • instance:使用指令的组件的实例
    • value:传给指令的值。例如,在 v-my-directive="1+1"中,value 的值为 2
    • oldValue:前一个值,仅在 beforeUpdate 和 updated 钩子中可用。无论值是否改变都可用
    • arg:传给指令的参数,可选。例如,在 v-my-directive:foo 中,arg 的值为 foo
    • modifiers:一个包含修饰符的对象。例如,在 v-my-directive.foo.bar 中,modifiers 对象的值为 {foo:true,bar:true}
    • dir:注册指令时作为参数传递的对象。如下面注册指令的代码
app.directive('focus',{
  mounted(el) {
    el.focus()
  }
})

dir 是下面的对象

{
  mounted(el) {
    el.focus()
  }
}
  • vnode:Vue编译生成的虚拟节点
  • oldVnode:上一个虚拟节点,仅在 beforeUpdate 和 updated 钩子中可用

需要注意的是,除了 el 参数外,其它参数都应该是只读,切勿进行修改。
编写一个自定义指令,在其钩子函数中将各个参数输出。如下:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		
	</head>
	<body>
		<div id="app">
		    <p v-demo:foo.a.b="message"></p>
		</div>
	
		<script src="https://unpkg.com/vue@next"></script>
		<script>
		    const app = Vue.createApp({
		        data() {
    			    return {
    			        message: '斗罗大陆'
    			    }
			    }
		    })
		    
			app.directive('demo', {
			    mounted (el, binding, vnode) {
    			    let s = JSON.stringify
    			    el.innerHTML =
    			      'instance: '   + s(binding.instance) + '<br>' +
    			      'value: '      + s(binding.value) + '<br>' +
    			      'argument: '   + s(binding.arg) + '<br>' +
    			      'modifiers: '  + s(binding.modifiers) + '<br>' +
    			      'vnode keys: ' + Object.keys(vnode).join(', ')
    			    
			    }
			})
			app.mount('#app')
		</script>
	</body>
</html>

将 bind 钩子函数的所有参数信息取出来拼接成字符串,赋值给 div 元素的 innerHTML 属性。渲染结果如下:
在这里插入图片描述

5.2.3 动态指令参数

自定义的指令也可以使用动态参数,例如,在 v-mydirective:[argument]=“value” 中,argument 参数可以根据组件实例数据进行更新,这使自定义指令可以在应用中被灵活运用。
例5-19

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		
	</head>
	<body>
		<div id="app">
			<!--直接给出指令的参数-->
			<p v-pin:top="100">
				无限恐怖
			</p>
			<!--使用动态参数-->
			<p v-pin:[direction]="100">
				恐怖复苏
			</p>
		</div>
	
		<script src="https://unpkg.com/vue@next"></script>
		<script>
		    const app = Vue.createApp({
		        data() {
    			    return {
    			        direction: 'left'
    			    }
			    }
		    })
			app.directive('pin', {
			  beforeMount(el, binding, vnode) {
			  	el.style.position = 'fixed';
			  	let s = binding.arg || 'left';
	    		el.style[s] = binding.value + 'px'
			  }
			})
			app.mount('#app')
		</script>
	</body>
</html>

浏览器的显示结果如下:
在这里插入图片描述

5.2.4 函数简写

如果自定义指令在 mounted 和 updated 钩子函数中的行为一致,且只需要用到这两个钩子函数,那么可以在注册时传递一个函数对象作为参数。如下:

app.directive('color-swatch',(el,binding) =>{
  el.style.backgroundColor = binding.value
})

5.2.5 对象字面量

如果指令需要多个值,则可以传入一个 JavaScript 对象字面量。但要记住的是,指令可以接受所有合法的 JavaScript 表达式。

<div v-demo="{color:'white',text:'hello'}"></div>
app.directive('demo',(el,binding)=>{
  console.log(binding.value.color) //white
  console.log(binding.value.text) //hello
})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只小熊猫呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值