上篇内容是关于 mixin 混入的一些操作, 也是关于代码复用层面的, 本篇讲自定义指令 directive 也是为了实现复用而设计的一些小功能啦.
先来看看, 如果不用 directive 的场景下, 如何进行代码复用.
<!DOCTYPE html>
<html lang="en">
<head>
<title>不用 directive 时</title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="root"></div>
<script>
const app = Vue.createApp({
// 当页面加载完就让其自动获得焦点
mounted () {
this.$refs.input1.focus()
this.$refs.input2.focus()
this.$refs.input3.focus()
},
template: `
<div>
<input ref="input1" />
<input ref="input2" />
<input ref="input3" />
</div>
`
})
const vm = app.mount('#root')
</script>
</body>
</html>
可以看到这里的 this.$refs.input2.focus( ) 被重复调用了3次, 这种写法是没有能实现咱说的复用的. 而 derective 则就是为了将其封装为一个指令而设计的啦.
全局指令 directive
先来一个直观演示, 如上例我们自定义一个名为 focus 的全局指令, 功能是使其 dom 能获得焦点.
<!DOCTYPE html>
<html lang="en">
<head>
<title>自定义全局指令</title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="root"></div>
<script>
const app = Vue.createApp({
template: `
<div>
<input ref="input1" v-focus />
</div>
`
})
// 自定义一个全局指令 focus, 作用是让其 dom 获得焦点
app.directive('focus', {
mounted (el) {
el.focus()
}
})
const vm = app.mount('#root')
</script>
</body>
</html>
全局指令即可通过 app.directive('xxx', { }) 来定义, 使用的使用直接在 dom 中通过 v-xxx 即可.
局部指令 directive
同局部组件, 局部 mixin 几乎一样的操作, 就是在 vue 之外写一个对象, 然后通过 vue 中的某个属性进行引入啦.
<!DOCTYPE html>
<html lang="en">
<head>
<title>自定义局部指令</title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="root"></div>
<script>
// 自定义局部指令
const myDirective = {
focus: {
mounted (el) {
el.focus()
}
}
}
const app = Vue.createApp({
directives:myDirective,
template: `
<div>
<input ref="input1" v-focus />
</div>
`
})
const vm = app.mount('#root')
</script>
</body>
</html>
需要注意这里的引入写法是键值对的方式哦, 感觉也是乱七八糟的:
directives:myDirective
当然关于指令的作用周期也可以是结合咱的8大生命周期函数如下:
-
beforCreate, created: 在 vue 实例创建前, 后 的自动执行
-
beforMount, mounted: 在 vue 组件渲染到页面前, 后 的自动执行
-
beforUpdate, updated: 在 data 数据变化前, 数据变化后并渲染后 的自动执行
-
beforUnmount, unmounted: 在 vue 实例被销毁 前, 后 的自动执行
自定义指令开发
这里简单来开发一个指令叫 v-position 实现元素的位置自定义效果.
<!DOCTYPE html>
<html lang="en">
<head>
<title>自定义指令开发</title>
<script src="https://unpkg.com/vue@3"></script>
<style>
.test {
position: absolute;
height: 100px;
background: orange;
}
</style>
</head>
<body>
<div id="root"></div>
<script>
const app = Vue.createApp({
data () {
return { num: 200 }
},
template: `
<div>
<div v-position="num" class="test">v-position 测试</div>
</div>
`
})
// 自定义全局指令 v-position 开发
app.directive('position', {
mounted (el, binding) {
el.style.top = binding.value + 'px'
},
updated (el, binding) {
el.style.top = binding.value + 'px'
}
})
const vm = app.mount('#root')
</script>
</body>
</html>
当只有 mounted 和 updated 的时候可以有个简写如下:
app.directive('position', (el, binding) => {
el.style.top = binding.value + 'px'
})
结合之前我们对指令传参的应用, 如 v-on:click = 'xxx' 的这种写法, 也是可以将参数传递给到 binding 的 arg中的, 那这样就可以对咱的这个 position 做 top, right, bottom, left 等参数啦.
<!DOCTYPE html>
<html lang="en">
<head>
<title>自定义指令开发</title>
<script src="https://unpkg.com/vue@3"></script>
<style>
.test {
position: absolute;
height: 100px;
background: orange;
}
</style>
</head>
<body>
<div id="root"></div>
<script>
const app = Vue.createApp({
data () {
return { num: 200 }
},
// v-position:xxx 这里就可以传参数啦
template: `
<div>
<div v-position:left="num" class="test">v-position 测试</div>
</div>
`
})
// 自定义全局指令 v-position 开发
app.directive('position', (el, binding) => {
// console.log('binding:', binding)
el.style[binding.arg] = binding.value + 'px'
})
const vm = app.mount('#root')
</script>
</body>
</html>
其实核心就是这个 binding 对象啦:
app.directive('position', (el, binding) => {
el.style[binding.arg] = binding.value + 'px'
})
小结
- 自定义指令 directive 结合生命周期函数可是实现代码的复用
- 分为全局指令 app.directive( ) 和局部指令 directives: xxx 的形式
- 自定义开发即是对传输的 el 进行操作, 也可以通过 binding 对象进行传参 arg