自定义指令
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/c32a3d007dd186f91119483e161debdd.png)
一、简单使用
<template>
<div>
<AVue v-move:aaa.style="{ background: 'red', width: '100px', height: '200px' }"></AVue>
</div>
</template>
<script setup lang="ts">
import { Directive } from 'vue'
import AVue from './components/example/AVue.vue'
import { DirectiveBinding } from 'vue';
type Style = {
background?: string,
width?: string,
height?: string
}
const vMove: Directive = {
created() { },
beforeMount() { },
mounted(el: HTMLElement, binding: DirectiveBinding<Style>) {
const background = binding.value.background
const width = binding.value.width
const height = binding.value.height
el.style.width = width ? width : '500px'
el.style.height = height ? height : '500px'
el.style.background = background ? background : 'yellow'
},
beforeUpdate() { },
updated() { },
beforeUnmount() { },
unmounted() { }
}
</script>
<style lang="scss" scoped></style>
二、封装一个鉴权指令
<template>
<div>
<div class="btns">
<button v-has-permission="'permission:shop:preview'">查看</button>
<button v-has-permission="'permission:shop:edit'">编辑</button>
<button v-has-permission="'permission:shop:delete'">删除</button>
</div>
</div>
</template>
<script setup lang="ts">
import { Directive } from 'vue';
const permission = ref([
"permission:shop:preview",
"permission:shop:edit",
"permission:shop:delete"
])
const vHasPermission:Directive<HTMLElement, string> = (el, binding) => {
const show = permission.value.includes(binding.value)
if (!show) {
el.style.display = 'none'
}
}
</script>
<style lang="scss" scoped>
button {
margin-left: 20px;
}
</style>
三、封装一个移动元素的指令
<template>
<div>
<DialogVue v-move></DialogVue>
</div>
</template>
<script setup lang="ts">
import DialogVue from './components/example/Dialog.vue'
import { Directive } from 'vue';
const vMove: Directive<HTMLElement, void> = (el) => {
let offsetX = 0
let offsetY = 0
const donwEventHandler = (downEvent: MouseEvent) => {
el.style.cursor = 'move'
el.addEventListener('mousemove', moveEventHandler)
console.log('按下时的坐标',downEvent)
offsetX = downEvent.offsetX
offsetY = downEvent.offsetY
}
const moveEventHandler = (moveEvent: MouseEvent) => {
let x = moveEvent.clientX - offsetX
let y = moveEvent.clientY - offsetY
const minX = 0
const minY = 0
const maxX = window.innerWidth - el.offsetWidth
const maxY = window.innerHeight - el.offsetHeight
const totalWidth = el.offsetWidth + x
const totalHeight = el.offsetHeight + y
if (x >= maxX) {
x = maxX
}
if (x <= minX) {
x = minX
}
if (y >= maxY) {
y = maxY
}
if (y <= minY) {
y = minY
}
el.style.left = x + "px"
el.style.top = y + "px"
}
const upEventHandler = (upEvent: MouseEvent) => {
el.style.cursor = 'unset'
el.removeEventListener('mousemove', moveEventHandler)
}
el.addEventListener('mousedown', donwEventHandler)
el.addEventListener("mouseup", upEventHandler)
}
</script>
<style lang="scss" scoped></style>
自定义指令实现懒加载
<template>
<div>
<div>
<img v-for="item in arr" v-lazy="item" style="width: 390px; height: 500px;">
</div>
</div>
</template>
<script setup lang="ts">
import { Directive } from 'vue';
const imageList: Record<string, { default: any }> = import.meta.glob('./assets/*.*', { eager: true })
let arr = Object.values(imageList).map(item => item.default)
const vLazy: Directive<HTMLImageElement, string> = async (el, bingding) => {
const def = await import('./assets/vue.svg')
el.src = def.default
const observer = new IntersectionObserver((entries) => {
if (entries[0].intersectionRatio > 0) {
el.src = bingding.value
observer.unobserve(el)
}
});
observer.observe(el)
}
</script>
<style lang="scss" scoped></style>