自定义指令
- 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.valueelement.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.valueelement.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.valueelement.focus()}
})
</script>
- 函数式
<script type="text/javascript">
Vue.directive('fbind',function(element,binding){element.value = binding.valueelement.focus()
})
</script>