1.定义
v-model 和 v-show 都是指令,vue推荐是使用数据驱动的方式改变dom,但在特殊场景,我们需要操作dom, 自定义指令就是一种有效的补充和扩展,不仅可用于定义任何的DOM操作,并且是可复用的。
2.声明范围
2.1全局
Vue.directive('focus',{
inserted(el){
el.focus()
}
})
2.2局部
new Vue({
el:"#app"
directives:{
focus:{
inserted(el){
el.focus()
}
}
}
})
3.指令的生命周期与参数传递
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
<title>自定义指令</title>
</head>
<body>
<div id="app">
{{ message }}
<input v-if="isShow" v-focus:foo.a.b="focusVal" v-model="message">
<!--<input v-if="isShow" v-focus="focusObjVal" v-model="message">-->
<button type="button" @click="changeClick">改变内容</button>
<button type="button" @click="deleteClick">删除组件</button>
</div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!',
focusVal: '1111', //可以是个方法或者对象
focusObjVal: { name : "张三", age : 18},
isShow: true
},
methods:{
changeClick(){
this.message = "点击了"
},
deleteClick(){
this.isShow = false
}
},
directives: {
focus: {
// 只调用一次,指令第一次绑定到元素时调用
bind(el,binding,vnode,oldVnode){
console.log("name",binding.name)
console.log("arg",binding.arg)
console.log("expression",binding.expression) //表达式
console.log("value",binding.value) //对应解析的内容
console.log("modifiers",binding.modifiers) //这里是修饰符{a:true,b:true} 用于特殊逻辑判断,可以参考vue的click里的.stop .prevent
},
// 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)
inserted: function (el,binding) {
console.log("inserted")
el.focus()
},
//被绑定元素所在的模板更新时调用,而不论绑定值是否变化。只有内容发生变化才触发。
update(el,binding){
console.log("update")
console.log("modifiers",binding.modifiers)
},
//被绑定元素所在模板完成一次更新周期时调用。一般在update之后都会触发。
componentUpdated(el,binding){
console.log("componentUpdated")
},
//只调用一次, 指令与元素解绑时调用。
unbind(el,binding){
console.log("unbind")
}
}
}
});
</script>
</body>
</html>
4.指令与外部数据交互
通过指定对象,把外部方法与指令内的方法进行绑定,使得指令内可以直接调用外部的方法,并且可以带入参数。
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
<title>自定义指令</title>
</head>
<body>
<div id="app">
<div v-drag="{setVal:setValFn,showVal:showValFn,data: outData}">自定义指令</div>
</div>
<script>
var app = new Vue({
el:"#app" ,
data(){
return {
outData: 1,
a: 2,
b: 3
}
},
methods: {
setValFn(val1,val2) {
this.a = val1;
this.b = val2;
},
showValFn() {
console.log("this.a",this.a)
console.log("this.b",this.b)
}
},
directives: {
drag: {
bind(el,binding) {
var value1 = 11;
var value2 = 22;
binding.value.setVal(value1, value2); // 外部的data会接收到内部的value1和value2,执行方法setValFn();
binding.value.showVal();
console.log(binding.value.data) // 会得到外部传入的 outData : 1
}
}
}
})
</script>
</body>
</html>