为什么要有自定义指令directive
希望input标签在加载的时候就处于focus的状态
1.使用自定义指令directive之前
【敲代码】
const app = Vue.createApp({
mounted(){
this.$refs.input.focus()
},
template: `
<div>
<input ref="input"/>
</div>
`
})
const vm = app.mount('#root')
对于简单的DOM处理,获取DOM去处理是可以的
但是这种让输入框自动聚焦的代码是没法复用的
如果还有一个input1呢?就还需要再写一次 this.$refs.input1.focus()
对DOM的一些操作可以通过封装自定义指令来实现DOM逻辑的复用
2.使用自定义指令directive之后
全局的自定义指令
定义一个全局的自定义指令focus
【敲代码】
const app = Vue.createApp({
template: `
<div>
<input v-focus/>
</div>
`
})
app.directive('focus',{
mounted(el){
el.focus();
}
})
const vm = app.mount('#root')
备注
- 定义了一个叫
focus
的自定义指令 - 如果想使用自定指令就
v-focus
mounted
是自定义指令的生命周期函数,它的意思是当指令挂载到DOM上的某个元素并且元素挂载到页面上之后自动执行的函数,执行的时候接收的参数el表示模板中使用v-focus
自定义指令的元素mounted
钩子函数执行的时候执行这个元素的聚焦
局部的自定义指令
【敲代码】
// 定义局部的自定义指令
const myDirectives = {
focus: {
mounted(el) {
el.focus();
}
}
}
const app = Vue.createApp({
directives: myDirectives,
template: `
<div>
<input v-focus/>
</div>
`
})
// 定义全局的自定义指令
app.directive('focus', {
mounted(el) {
el.focus()
}
})
备注
- 如果想要使用局部的自定义指令就要在组件中使用
directives:xxx
引入这个定义好的局部自定义指令
自定义指令中的其他钩子函数
自定义指令中的钩子函数除了mounted
之外还有其他的生命周期函数,如
beforeMount:当元素即将挂载到页面时自动触发的函数
mounted:当元素挂载到页面时自动触发的函数
beforeUpdate:当元素重新渲染前自动触发的函数
uodated:当元素重新渲染时自动触发的函数
beforeUnmount:当元素重新渲染前自动触发的函数
unmounted:当元素重新渲染时自动触发的函数
自定义指令v-pos
控制元素的位置
1. 初体验
使用自定义指令v-pos
的元素,让其距离顶部200px
【敲代码】
const app = Vue.createApp({
template: `
<div>
<div v-pos="200" class="header">
<input />
</div>
</div>
`
})
app.directive('pos', {
mounted(el) {
el.style.top="200px"
}
})
const vm = app.mount('#root')
2. 让指令接收额外的参数,如v-pos=400
如果想要让其距离顶部400px呢?
【敲代码】
const app = Vue.createApp({
template: `
<div>
<div v-pos="400" class="header">
<input />
</div>
</div>
`
})
app.directive('pos', {
mounted(el,binding) {
el.style.top = binding.value + "px"
}
})
const vm = app.mount('#root')
这样我们就可以自定义元素距离顶部的距离
备注
- 参数
binding.value
可以获取到v-pos=400
中的值400
3.将v-pos=400
中的值400绑定到data中去管理
【敲代码】
const app = Vue.createApp({
data() {
return {
top: 100
}
},
template: `
<div>
<div v-pos="top" class="header">
<input />
</div>
</div>
`
})
app.directive('pos', {
mounted(el,binding) {
el.style.top = binding.value + "px"
}
})
const vm = app.mount('#root')
当我们修改data中top的值时,发现页面并没有发生变化。因为数据发生变化后,mounted
并不会重新的执行
我们可以结合另外一个钩子函数,使用updated
钩子函数,当数据发生变化组件要重新渲染的时候自动触发
【敲代码】
const app = Vue.createApp({
data() {
return {
top: 100
}
},
template: `
<div>
<div v-pos="top" class="header">
<input />
</div>
</div>
`
})
app.directive('pos', {
mounted(el,binding){
el.style.top = binding.value + "px"
},
updated(el,binding) {
el.style.top = binding.value + "px"
}
})
const vm = app.mount('#root')
3.另外一种简写的写法
当自定义指令中只有mounted
和updated
两个钩子函数,并且这两个函数中的内容是相同的,那么就可以简写成下面这样的函数:
app.directive('pos',(el, binding) => {
console.log(binding);
el.style.top = binding.value + "px"
})
4.让指令支持参数和参数的值
可不可以像指令v-on:click
那样让自定义指令支持参数v-pos:abc
的写法?
【敲代码】
const app = Vue.createApp({
data() {
return {
top: 100
}
},
template: `
<div>
<div v-pos:abc="top" class="header">
<input />
</div>
</div>
`
})
// 简写
app.directive('pos',(el, binding) => {
console.log(binding);
el.style.top = binding.value + "px"
})
const vm = app.mount('#root')
【运行结果】
我们发现其实这个参数可以通过binding.arg
获取到
那么我们就可以使用自定义指令的参数和参数的值binding.arg
和binding.value
做些事情:我们可以使用带参数的自定义使元素不仅可以距离顶部xxx距离,还可以是距离左边/右边xxx距离
【敲代码】
const app = Vue.createApp({
data() {
return {
distance: 100
}
},
template: `
<div>
<div v-pos:left="distance" class="header">
<input />
</div>
</div>
`
})
// 简写
app.directive('pos',(el, binding) => {
console.log(binding);
el.style[binding.arg] = binding.value + "px"
})
const vm = app.mount('#root')
备注
这里要写成el.style[binding.arg] = binding.value + "px"
不要写成el.style.binding.arg = binding.value + "px"
当然不仅可以做到距离右边还可以做到距离下面、右边、左边,我们只需要修改自定义指令的参数即可
<div v-pos:bottom="distance" class="header">
<input />
</div>
<div v-pos:right="distance" class="header">
<input />
</div>
<div v-pos:left="distance" class="header">
<input />
</div>