目录
自定义指令的过程中所有对DOM元素的操作都要自己写。内置指令从某种程度上说其实就是把原生操作DOM进行了封装,如v-show本质也是对DOM元素的display进行设置为none
注意:有两种情况是没有 v- 的:
1. 该指令没有时报错,只会出现 v- 后面的内容,而没有 v-
2. 自定义指令时,直接写名,不应加 v-
自定义指令需要全新的配置项: directives
一、自定义指令_函数式
binding是指标签元素和指令的一种关联关系
v-bind是给标签中的某一个属性绑定时用的
函数式的函数有两个参数:第一个是与该指令绑定的真实的DOM元素 element,第二个参数是指令与标签元素的关系信息 binding,里面包含指令表达式的值 binding.value
big函数何时会被调用?
1. 指令与元素成功绑定时(一上来)会被调用;
2. 指令所在的模板被重新解析时(例如修改name时,模板重新解析,会调用big)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<!--
需求1:定义一个v-big 指令,和v-text 功能类似,但会把绑定的数值放大10倍。
需求2: 定义一个v-fbind 指令,和v-bind功能类似,但可以让其所绑定的
input元素默认获取焦点。
-->
<div id="root">
<h2>{{name}}</h2>
<h2>当前的n值是:<span v-text="n"></span></h2>
<h2>放大十倍后的n值是:<span v-big="n"></span></h2>
<button @click="n++">点我n+1</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
n:1,
name:'尚硅谷'
},
directives:{
/*
big函数何时会被调用?
1.指令与元素成功绑定时(一上来)会被调用;
2.指令所在的模板被重新解析时(例如修改name时,模板重新解析,会调用big)
*/
big(element,binding){
element.innerText = binding.value*10
console.log(element,binding);
}
}
})
</script>
</body>
</html>
二、自定义指令_对象式
需求2: 定义一个v-fbind 指令,和v-bind功能类似,但可以让其所绑定的 input元素默认获取焦点。
有些操作需要放到 input元素创建完成并添加到页面中代码后才能生效,如自动获取焦点 input.focus( )、input的父元素的背景色 input.parentElement.style.backgrounColor = 'blue' (还未放入页面的话,不知道其父元素是谁);但对于一些操作,就可以在元素未添加到页面前写,也生效,如:input.className 、input.value、事件绑定
对象式_自定义指令:能在特殊时刻调用特殊的函数,三个特殊的函数分别为:
指令与元素成功绑定时(一上来): bind(element, binding) { }
指令所在元素被插入页面时调用的函数:inserted(element, binding){ }
指令所在的模板被重新解析时调用的函数:update(element, binding) { }
使用函数式与 对象式自定义指令的区别:主要是函数式中对于指令所在元素被插入页面时这一特殊时刻不包含。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>document</title>
<style>
.demo{
background-color: orange;
}
</style>
</head>
<body>
<button id="btn">点我创建一个输入框</button>
<script type="text/javascript">
const btn = document.getElementById('btn')
btn.onclick = ()=>{
const input = document.createElement('input')
input.className = 'demo'
input.value = '99'
input.onclick = ()=>{alert(1)}
// 以上这些操作都可以放在input被放到页面的代码前
console.log(input.parentElement);//null
document.body.appendChild(input)
// input框出现的时候自动获取焦点
input.focus()
// 使input父元素的背景色是天蓝色
input.parentElement.style.backgroundColor = 'skyblue'
//这些操作必须放在input被放到页面的代码后面
console.log(input.parentElement);//body
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<!--
需求1:定义一个v-big 指令,和v-text 功能类似,但会把绑定的数值放大10倍。
需求2: 定义一个v-fbind 指令,和v-bind功能类似,但可以让其所绑定的
input元素默认获取焦点。
-->
<div id="root">
<h2>{{name}}</h2>
<h2>当前的n值是:<span v-text="n"></span></h2>
<h2>放大十倍后的n值是:<span v-big="n"></span></h2>
<button @click="n++">点我n+1</button>
<hr>
<input type="text" v-fbind:value="n">
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
n:1,
name:'尚硅谷'
},
directives:{
/*
big函数何时会被调用?
1.指令与元素成功绑定时(一上来)会被调用;
2.指令所在的模板被重新解析时(例如修改name时,模板重新解析,会调用big)
*/
big(element,binding){
element.innerText = binding.value*10
console.log(element,binding);
},
// 写成函数式无法获得元素被放入页面的时机,使得 element.focus()初次调用失效
/* fbind(element, binding){
element.value = binding.value
element.focus()//一打开页面不生效,但是点击按钮之后都生效的原因:
// 函数在指令与元素成功绑定时调用函数,但此时还未放入到页面
} */
// 写成对象式,能在特殊的时刻调用特殊的函数
fbind:{
// 当指令与元素成功绑定时
bind(element,binding){
// console.log('bind');
element.value = binding.value
},
// 当指令所在元素被插入页面时
inserted(element,binding){
// console.log('inserted');
element.focus()
},
// 指令所在的模板被重新解析时
update(element,binding){
// console.log('update');
element.value = binding.value
// element.focus()
}
}
}
})
</script>
</body>
</html>
三、自定义指令_总结
所有指令相关里的this 都不是Vue实例对象,而是window
自定义指令总结:
一、定义语法:
(1).局部指令:
new Vue({
directives:{指令名:配置对象}
})
或者
new Vue({
directives:{ 指令名: 回调函数 }
})
(2).全局指令:
Vue.directive(指令名,配置对象) 或者 Vue.directive(指令名,回调函数)
二、配置对象中常用的三个回调:
(1).bind :指令与元素成功绑定时调用;
(2).inserted :指令所在元素被插入页面时调用;
(3).update :指令所在模板结构被重新解析时调用。
三、备注:
1.指令定义时不加 v-,但使用时要加 v-;
2.指令名如果是多个单词,要使用kebab-case 的命名方式,不要使用cameCase(驼峰)命名,同时在自定义对象式中该指令应用引号引起来,因为如果key里面出现 - 形式,key不能使用简写形式,应用引号包起来
<div id="root">
<h2>{{name}}</h2>
<input type="text" v-big-number=""> //指令名由多个单词组成时,应使用横线,而不是驼峰命名
</div>
<script type="text/javascript">
const vm = new Vue({
el: '#root',
data: {
n: 1,
name: '哈哈哈'
},
directives: {
'big-number':function() { //要使用引号包起来,如果key里面出现 - 形式,key不能使用简写形式,应用引号包起来
}
}
})
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<!--
需求1:定义一个v-big 指令,和v-text 功能类似,但会把绑定的数值放大10倍。
需求2: 定义一个v-fbind 指令,和v-bind功能类似,但可以让其所绑定的
input元素默认获取焦点。
-->
<div id="root">
<h2>{{name}}</h2>
<h2>当前的n值是:<span v-text="n"></span></h2>
<h2>放大十倍后的n值是:<span v-big="n"></span></h2>
<!-- <h2>放大十倍后的n值是:<span v-big-number="n"></span></h2> -->
<button @click="n++">点我n+1</button>
<hr>
<input type="text" v-fbind:value="n">
</div>
<div id="root2">
<input type="text" v-fbind2:value="x">
</div>
<script type="text/javascript">
Vue.config.productionTip = false
// 全局自定义指令
Vue.directive('fbind2',{
// 当指令与元素成功绑定时
bind(element,binding){
element.value = binding.value
},
// 当指令所在元素被插入页面时
inserted(element,binding){
element.focus()
},
// 指令所在的模板被重新解析时
update(element,binding){
element.value = binding.value
// element.focus()
}
})
Vue.directive('big2',function(element,binding){
console.log('big',this);//window
element.innerText = binding.value*10
console.log(element,binding);
})
new Vue({
el:'#root',
data:{
n:1,
name:'尚硅谷'
},
directives:{
/*
big函数何时会被调用?
1.指令与元素成功绑定时(一上来)会被调用;
2.指令所在的模板被重新解析时(例如修改name时,模板重新解析,会调用big)
*/
/* 'big-number'(element,binding){//对象里所有的key都是字符串,所以要给big-number加引号
//'big-number'(element,binding){}是'big-number':function(element,binding)的简写形式
element.innerText = binding.value*10
console.log(element,binding);
}, */
big(element,binding){
console.log('big',this);//window
element.innerText = binding.value*10
console.log(element,binding);
},
/* fbind(element,binding){
element.value = binding.value
element.focus()//报错,因为element.focus()的时机错误
} */
fbind:{
// 当指令与元素成功绑定时
bind(element,binding){
// console.log('bind');
console.log('fbind-bind',this);//window,注意此处的this是window
element.value = binding.value
},
// 当指令所在元素被插入页面时
inserted(element,binding){
// console.log('inserted');
console.log('fbind-inserted',this);//window
element.focus()
},
// 指令所在的模板被重新解析时
update(element,binding){
// console.log('update');
console.log('fbind-update',this);//window
element.value = binding.value
// element.focus()
}
}
}
})
new Vue({
el:'#root2',
data:{
x:1,
}
})
</script>
</body>
</html>