什么是自定义指令Directive
Vue 内置的一系列指令 (比如 `v-model` 或 `v-show`) 等常用的指令。
Vue 还允许你注册自定义的指令 (Custom Directives)。
一个自定义指令由一个包含类似组件生命周期钩子的对象来定义。
钩子函数会接收到指令所绑定元素作为其参数。
指令钩子 (指令的生命周期)
const myDirective = {
// 在绑定元素的 attribute 前
// 或事件监听器应用前调用
created(el, binding, vnode, prevVnode) {
// 下面会介绍各个参数的细节
},
// 在元素被插入到 DOM 前调用
beforeMount(el, binding, vnode, prevVnode) {},
// 在绑定元素的父组件
// 及他自己的所有子节点都挂载完成后调用
mounted(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件更新前调用
beforeUpdate(el, binding, vnode, prevVnode) {},
// 在绑定元素的父组件
// 及他自己的所有子节点都更新后调用
updated(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件卸载前调用
beforeUnmount(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件卸载后调用
unmounted(el, binding, vnode, prevVnode) {}
}
创建一个拖拽指令
function dragable(el: HTMLElement) {
el.style.zIndex = '9999'
el.style.position = 'relative'
el.style.top = '0px'
el.style.left = '0px'
el.onmousedown = (ev) => {
let { width, height, x, y } = el.getBoundingClientRect()
let mouseX = ev.pageX
let mouseY = ev.pageY
let elTop = Number(el.style.top.split('px')[0])
let elLeft = Number(el.style.left.split('px')[0])
let clientWidth = document.body.clientWidth
let clientHeight = document.body.clientHeight
document.onmousemove = (ev) => {
let distanceWidth = ev.pageX - mouseX
let distanceHeight = ev.pageY - mouseY
// 边界测试
// 左边界
if (x + distanceWidth <= 0) {
distanceWidth = -x
}
// 右边界
if (x + width + distanceWidth >= clientWidth ) {
distanceWidth = clientWidth - width - x
}
// 上边界
if (y + distanceHeight <= 0) {
distanceHeight = -y
}
// 下边界
if (y + height + distanceHeight >= clientHeight ) {
distanceHeight = clientHeight - height - y
}
el.style.left = (elLeft + distanceWidth) + 'px';
el.style.top = (elTop + distanceHeight) + 'px'
}
document.onmouseup = (ev) => {
document.onmousemove = null
document.onmouseup = null
}
}
}
export default {
name: "dragable",
mounted(el: HTMLElement, binding: any) {
// binging.value
dragable(el)
}
}
局部注册
方式一
<template>
<div class="test" v-dragable>这是可以拖拽的内容</div>
</template>
<script setup lang="ts">
import dragable from "../directive/dragable";
const vDragable = dragable;
</script>
方式二
<template>
<div class="test" v-dragable>这是可以拖拽的内容</div>
</template>
<script lang="ts">
import dragable from "../directive/dragable";
export default {
directives: {
// 在模板中启用 v-dragable
dragable,
},
setup() {},
};
</script>
全局注册方式
我们可以把所有的自定义指令放在一个目录里并创建一个入口函数
// dirrectives.js
import dragable from "./dragable.js"
import lazyload from './lazyload.js'
let directivesArr = [dragable,lazyload]
export default {
install(app, options) {
directivesArr.forEach(item=>{
app.directive(item.name, item)
})
}
}
在main.ts中注册指令
import { createApp } from 'vue'
import App from './App.vue'
import store from './store'
import directives from './directive'
const app = createApp(App)
app.use(store)
app.use(directives)
app.mount('#app')
使用
<template>
<div class="test">
<div class="p1" v-dragable>p1</div>
</div>
<!-- <img v-lazyload="imgSrc" @click="changeIt" > -->
</template>