自定义指令
从某种程度上来说,Vue中的自定义指令就是把原生DOM操作进行了一次封装
指令是不能脱离元素【标签】存在的
定义指令:big
使用指令:v-big
值的写法:对象【可以处理一些细节上的问题】和函数
定义指令可以通过两种方式,函数式和对象式
1. 函数式
指令名(真实DOM元素[element], 绑定对象[bingding]){
}
真实DOM元素[element]:指令所在的元素
注:element instanceof HTMLElement 可以证明element是真实DOM元素,除了这种方法可以证明,console.dir(element)也可以看到element拥有所有真实DOM的属性和方法,也能够说明element是真实DOM元素
绑定对象[bingding]有几个重要的属性:
- value:指令接收到的表达式的值
- expression:指令接收到的表达式
- name:指令名
- rawName:使用指令时要用的名字
函数式指令何时会被调用?
1.指令与元素成功绑定时(一上来)【指令与元素绑定成功仅仅代表着在内存里面建立了指令与元素之间的关系,元素此时还没有被放到页面上】。
2.指令所在的模板被重新解析时。
2. 对象式
DOM操作可分为两类操作
-
元素放到页面之前和放到页面之后进行该操作效果是一样的,比如给text类型的input框设置value,放到页面之前进行设置value的操作和将input框放到页面之后再进行设置value的操作结果是相同的。
-
元素放到页面之后进行该操作才能够生效,比如让text类型的input框获取焦点,input框还没放到页面上呢,是不可能进行获取焦点的操作的。【这些操作时机很重要,时机不对,操作不会生效】
<body> <button type="button" id="btn">点击增加一个input框</button> <script type="text/javascript" charset="utf-8"> // 拿到id为btn的element元素 const btn = document.getElementById('btn') // 给btn元素绑定单击事件 btn.onclick = () =>{ // 创建一个input框【此时还没放到页面上】 const input = document.createElement('input') // input框放到界面上之前为input框设置值【操作可以生效】 input.value = 99 // input框放到界面上之前为input框设置类名,引用样式【操作可以生效】 input.className = 'demo' // input框放到界面上之前为input框绑定单击事件【操作可以生效】 input.onclick = () =>{ alert(1) } // input框放到界面上之前设置input框父级元素的背景色样式【操作不可以生效】 // input.parentElement.style.backgroundColor = '#FF0000' // 放在这里是获取不到焦点的,获取焦点的操作有个前提是元素必须已经在页面上了 // input框放到界面上之前让input框获取焦点【操作不可以生效】 // input.focus() // 将input框放到body中【这一步就放到了页面上】 document.body.appendChild(input) // input框放到界面上之后设置input框父级元素的背景色样式【操作可以生效】 input.parentElement.style.backgroundColor = '#FF0000' // input框已经放到页面上了,所以能够获取到焦点 // input框放到界面上之后让input框获取焦点【操作可以生效】 input.focus() } </script> </body>
对象式自定义指令中,包含了若干个钩子函数,这些钩子函数的名称是固定的,Vue在特定时间点会调用我们定义的钩子函数
常用的钩子函数
- bind(element, bingding):指令与元素成功绑定时(一上来)被Vue调用【此时元素已经有了,指令也与元素进行了绑定,但还没放到页面上】
- inserted(element, bingding):指令所在元素被插入页面时被Vue调用【此时元素已经被放到了页面上】
- update(element, bingding):指令所在的模板被重新解析时被Vue调用
注:bind()和update()中的操作一般都是相同的,函数式自定义指令相当于对象式自定义指令的简写方式,这种方式中仅仅定义了bind()和update()两个钩子函数
<body>
<div id="root">
<h2>n的值是:{{n}}</h2>
<h2>n放大后的值是:<span v-bing="n"></span></h2>
<button type="button" @click="n++">n++</button><br>
<input type="text" v-fbind:value="n"/>
</div>
<script type="text/javascript">
//阻止 vue 在启动时生成生产提示。
Vue.config.productionTip = false
const vm = new Vue({
el: "#root",
data:{
n: 1
},
computed: {
},
methods: {
},
// 定义指令
directives: {
bing(element, bingding){
// element.innerText:当前元素的文本内容
element.innerText = bingding.value * 10
console.log(element,bingding)
},
// fbind(element, bingding){
// element.value = bingding.value
// 初次加载未成功获取到焦点:该函数初次调用是在指令与元素进行绑定时,此时页面上还没有input框,所以无法绑定
// 点击按钮修改n值后成功获取到焦点:修改n值后,模板重新解析,该函数重新调用,此时页面上已经存在input框了,所以成功绑定
// 函数式指令函数执行的时机是固定的,指令与元素成功绑定时(一上来)和指令所在的模板被重新解析时
// 要想初次加载就能获取到焦点,必须在Vue将元素放到页面上之后再执行获取焦点的操作
// element.focus()
// }
fbind: {
bind(element, bingding){
element.value = bingding.value
},
inserted(element, bingding){
element.focus()
},
update(element, bingding){
element.value = bingding.value
}
}
}
})
</script>
</body>
3. 几个坑
-
指令名命名,如果指令名包含了多个单词【比如bignumber】,多个单词之间要用'-'连接,'big-number'
如果对象中的key包含了'-'这个符号,key值就要用引号包裹起来''
-
指令回调函数【对象式中的bind、inserted、update和函数式】中的this都是window
-
Vue实例中定义的directives指令都是局部指令,其他Vue实例中用不了
<body>
<div id="root">
<h2>n的值是:{{n}}</h2>
<h2>n放大后的值是:<span v-bing="n"></span></h2>
<button type="button" @click="n++">n++</button><br>
<input type="text" v-fbind:value="n"/>
</div>
<div id="root2">
<span v-bing="x"></span>
</div>
<script type="text/javascript">
//阻止 vue 在启动时生成生产提示。
Vue.config.productionTip = false
//定义函数式全局指令
Vue.directive('bing', function(element, bingding){
element.innerText = bingding.value * 10
})
//定义对象式全局指令
Vue.directive('fbind',{
bind(element, bingding){
console.log(this)
element.value = bingding.value
},
inserted(element, bingding){
console.log(this)
element.focus()
},
update(element, bingding){
console.log(this)
element.value = bingding.value
}
})
const vm = new Vue({
el: "#root",
data:{
n: 1
},
computed: {
},
methods: {
},
// 定义局部指令
directives: {
// 定义函数式局部指令
// bing(element, bingding){
// // element.innerText:当前元素的文本内容
// element.innerText = bingding.value * 10
// console.log(element,bingding)
// console.log(this)
// },
// 定义对象式局部指令
// fbind: {
// bind(element, bingding){
// console.log(this)
// element.value = bingding.value
// },
// inserted(element, bingding){
// console.log(this)
// element.focus()
// },
// update(element, bingding){
// console.log(this)
// element.value = bingding.value
// }
// }
}
})
new Vue({
el: '#root2',
data:{
x: 2
}
})
</script>
</body>
4. 总结
自定义指令总结:
一、定义语法:
(1).局部指令:
new Vue({ new Vue({
directives:{指令名:配置对象} 或 directives{指令名:回调函数}
}) })
(2).全局指令:
Vue.directive(指令名,配置对象) 或 Vue.directive(指令名,回调函数)
二、配置对象中常用的3个回调【钩子函数】:
(1).bind:指令与元素成功绑定时调用。
(2).inserted:指令所在元素被插入页面时调用。
(3).update:指令所在模板结构被重新解析时调用。
三、备注:
1.指令定义时不加v-,但使用时要加v-;
2.指令名如果是多个单词,要使用kebab-case命名方式【短横线命名】,不要用camelCase命名。【驼峰命名】
标签:Vue,自定义,2x,value,element,指令,input,bingding
From: https://www.cnblogs.com/wzzzj/p/18045284