Vue中所有指令都以(v-)开头,即:v-指令名
1.全局自定义指令
使用Vue.directive('name',{})
定义全局自定义指令。
参数一'name'
:指令的名称,不需要加"v-"前缀;调用时需要加上。
参数二{}
:是一个对象,有相关钩子函数
(可选),可在特定阶段执行相关操作
1.1 钩子函数:
钩子函数:
- bind(),只调用一次,
指令在第一次绑定到元素身上时调用
。可以定义一个在绑定时执行的初始化动作
。- inserted(),
被绑定元素插入到父节点时调用
(父节点存在即可调用,不必存在于dom中)。- update(),所在组件的VNode跟新时调用,可能触发多次。但可能发生在其孩子的VNode跟新之前。指令的值可能发生了改变也可能没有。
- componentUpdated(),所在组件的VNode和其孩子的VNode全部跟新时调用。
- unbind(),只调用一次,指令与元素解绑时调用。
1.2 钩子函数参数:
- 第一个参数:永远是
el
,表示绑定此自定义指令的元素
,是个元素的js对象。 - 第二个参数:
binding,是一个对象
,包含以下参数:
- name,指令名,不包含v-前缀。
- value,指令的绑定值。如v-focus=“1+1”,value即为2。
- oldValue,指令绑定的前一个值,仅在update()和componentUpdated()钩子中使用。无论值是否改变都可用。
- expression,绑定值的字符串形式,如value中值即为"1+1"。
- 第三个参数:vnode,Vue 编译生成的虚拟节点。
- 第四个参数:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
总结:
//全局自定义指令
Vue.directive('clickoutside', //参数1 -- 不需要v-的指令名,调用的时候 v-clickoutside
{ //参数2 -- 是一个对象,里面是钩子函数,某个阶段执行某个操作
bind(){}, //指令在第一次绑定到元素身上时调用
inserted(){}, //被绑定元素插入到父节点时调用
update(){}, //组件的VNode虚拟节点跟新时调用
componentUpdated(){}, //所在组件的VNode和其孩子的VNode全部跟新时调用
unbind(
el, //钩子函数参数1 --- 绑定指令的元素的js对象
{ //钩子函数参数2 --- binding,一个对象
name, // --- 指令名
value, // ---- 指令的绑定值,例如:v-clickoutside="handleClose" ,value就是值 "handleClose"--这里是一个函数
oldValue, // ---- 指令的前一个绑定值,
expression // --- 绑定值的字符串形式, 例如:v-clickoutside="handleClose" 的value是函数handleClose,expression 是字符串expression
},
vnode, // 钩子函数参数3 --- Vue 编译生成的虚拟节点
preVnode){}, // 钩子函数参数4 --- 上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用
}
2. 私有自定义指令
在Vue实例中,增加directives属性,指向一个对象,自定义私有属性。属性名为自定义指令名,值为对象,内容为各个阶段执行的函数(钩子函数和参数同上)。
import Clickoutside from '../../../src/utils/clickoutside';
export default {
name:"ElSelect",
data(){
},
directives: { Clickoutside }, //私有自定义指令,只能在当前组件中使用该指令
}
或者
export default {
name:"ElSelect",
data(){
},
directives: { //directives属性,指向一个对象,对象中key是指令名,值是一个对象,对象里是钩子函数
Clickoutside:{ //私有自定义指令,只能在当前组件中使用该指令
bind(el,binding,vnode){}, //钩子函数参数,el--绑定元素的对象,binding是一个对象{指令名,指令绑定的值,指令绑定旧值,指令绑定值的字符串}
inserted(){},
update(){},
componentUpdated(){},
unbind(){}
}
},
}
3. 指令的简写形式
大多情况下,我们可能想在bind和update钩子函数上做重复动作,并不关心其他钩子函数,可以简写:
Vue.directive('color-swatch',function(el,binding){ //正常第2个参数是一个{},里面是bind和update钩子函数,这里简写成一个函数,函数的参数是(el,binding对象)
el.style.backgroundColor = binding.value; //指令绑定的元素的背景色设置为 指令绑定的值
});
4. 案例demo
自定义全局指令,使用v-focus
指令让页面刚加载完在输入框输入光标。通过v-fontweight="900" v-color-swatch="'red'"
私有指令改变样式
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<span v-fontweight="900" v-color-swatch="'red'">画画</span><input type="text">
<input type="text" v-focus>
</div>
<script>
//每个钩子函数的第一个参数永远是el,表示绑定这个指令的当前元素,是个原生的js对象
Vue.directive('focus',{
//每当指令绑定到元素身上的时候,会立即执行这个bind函数,只执行一次
bind(el){
//元素刚绑定了指令的时候,还没插入dom中,直接操作元素没用
//只有元素插入到dom中时,才能获取焦点,写在inserted中
//el.foucus();
},
//表示元素插入到dom中的时候,会执行inserted函数,触发一次
inserted(el){
el.focus();
},
//当VNode跟新的时候,会执行updated函数,可能会触发多次
updated(){
}
});
const vm = new Vue({
el:"#app",
directives:{ //自定义私有指令
'fontweight':{ //正常写法是这样--key:value形式
bind(el,binding){
el.style.fontWeight = binding.value;
},
},
'color-swatch'(el, binding) { //简写---为这样
el.style.backgroundColor = binding.value;
}
}
});
</script>
</body>
</html>
参考: