自定义指令
- 1 函数式
- 1.1 案例--v-text放大10倍
- 2 对象式
- 2.1 案例--v-fbind默认获取焦点(函数式)
- 2.2 案例--v-fbind默认获取焦点(对象式)
- 3 自定义指令容易犯的错
- 4 全局指令写法(参考过滤器写法):
1 函数式
1.1 案例–v-text放大10倍
<body>
<div id="root">
<h2>当前的n值是:<span v-text="n"></span></h2>
<h2>放大10倍的n值是:<span v-big="n"></span></h2>
<button @click="n++">点我n+1</button>
</div>
</body>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
n:1,
},
// --------定义一个全新的配置项----------
directives:{
//big:function(){} 简写如下
big(element,binding ){
element.innerText = binding.value * 10
}
//big函数被调用的情况:
//1.指令与元素成功绑定时(初次)
//2.指令所在的模板(div id ="root")重新解析时
}
})
</script>
innerText: 返回或设置元素中的纯文本内容,只适用于
IE/Chrome
big
函数收到的是两个参数:第一个是真实DOM
- 判断方法一
big(a,b){ console.dir(a) }
控制台输出了真实DOM身上所有的属性和方法
补充:
console.dir()
和console.log()
的区别- MDN上
console:dir()
静态方法的介绍
- 判断方法二
big(a,b){ console.log(a instanceof HTMLElement) }
检测a是不是HTMLElement的实例,输出为true
MDN上
instanceof
的定义:instanceof
运算符用于检测构造函数的prototype
属性是否出现在某个实例对象的原型链上
即:
在左边的检测对象的原型链上面查找右边的构造函数的prototype
属性是否出现,这个过程会沿着原型链一直找,直到找到原型链的最顶端Object.prototype
还没找到,那就只能返回null了,说明该对象不是这个构造函数的实例.
big
函数收到的是两个参数:第二个是个对象,且含有指令后面代数式的值、指令的名字、使用时指令的名字
2 对象式
2.1 案例–v-fbind默认获取焦点(函数式)
先通过案例来看一下,函数式写法会有什么问题。
<body>
<div id="root">
<h2>当前的n值是:<span v-text="n"></span></h2>
<input type="text" v-fbind:value="n">
<button @click="n++">点我n+1</button>
</div>
</body>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
n:1,
},
//--------定义一个全新的配置项-----------
directives:{
fbind(element,binding ){
element.value = binding.value
element.focus()
}
}
})
</script>
存在问题:
运行后没有获取焦点,点击按钮才有焦点。
原因:
- 按照顺序 指令与元素绑定 在 页面编译 之前。
- 那么函数的第一次调用是指令与元素成功绑定时,是在页面上呈现
input
之前。 - 但是模板是经过
vue
编译才放在页面上的,绑定在编译之前,而在input
出现在页面之前是无法获取焦点的。
点击按钮,n值修改,模板重新解析,重新调用指令fbind,现在input元素已在页面上,所以获取焦点。
此时fbind指令是函数形式,调用只存在以下两个时机:
- 指令与元素成功绑定时(初次)
- 指令所在的模板重新解析时
区分: span.innerText | input.value
2.2 案例–v-fbind默认获取焦点(对象式)
<body>
<div id="root">
<h2>当前的n值是:<span v-text="n"></span></h2>
<input type="text" v-fbind:value="n">
<button @click="n++">点我n+1</button>
</div>
</body>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
n:1,
},
//--------------定义一个全新的配置项-------------
directives:{
fbind:{
//以下函数都是固定的且常用的:
//指令与元素成功绑定时调用
bind(element,binding){
//此时可以写:样式、value值、绑定事件
input.value = binding.value
},
//指令所在元素被插入页面时
inserted(element,binding){
element.focus()
},
//指令所在的模板重新解析时
update(element,binding){
input.value = binding.value
element.focus()
}
}
}
})
</script>
bind和update函数的逻辑往往是一致的,所以也就有了函数式指令,因此如果没有其他特殊要求(获取焦点、拿到父元素),可以用函数式。
3 自定义指令容易犯的错
- 指令命名多个词用
-
连接(kebab-case),而不是写成驼峰命名法(camelCase),且directives配置项需要加‘’
,定义时不加v-
,但是使用时需要加。
例如定义一个input元素的指令
<input type="text" v-bigNumber:value="n">
应写成
<input type="text" v-big-number:value="n">
对应Vue实例中配置项的函数式:
'big-number'(){}
实际上big-number为directives对象里的key,当出现-
时不可简写 - 指令相关的回调函数的
this
不是vm而是Window
console.log('fbind',this)
输出为window - 自定义指令为局部指令,只给有定义的vue实例使用
即使用的模板的<div>
中的id 和Vue实例中的el相对应
<script type="text/javascript">
//对象式
new Vue({
directives:{
指令名:{配置对象}
}
})
或
//函数式
new Vue({
directives:{
指令名(参数1,...){
回调函数
}
}
})
</script>
4 全局指令写法(参考过滤器写法):
- 对象式:
<script type="text/javascript">
Vue.directive('fbind',{
bind(element,binding){
input.value = binding.value
},
inserted(element,binding){
element.focus()
},
update(element,binding){
input.value = binding.value
element.focus()
}
})
</script>
- 函数式
<script type="text/javascript">
Vue.directive('fbind',function(element,binding){
element.value = binding.value
element.focus()
})
</script>