Vue3——自定义指令

自定义指令

在这里插入图片描述

一、简单使用

<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) => {
    // 鼠标移动时,修改其left和top属性
    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';

// glob有两种模式,懒加载和马上加载,后面添加eager就是静态加载
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
  // 创建 Intersection Observer 实例
  const observer = new IntersectionObserver((entries) => {
    // 这个参数表示在可视区域的比例,如果大于0,表示已经能看到了
    if (entries[0].intersectionRatio > 0) {
      el.src = bingding.value
      // 取消监听
      observer.unobserve(el)
    }
  });
  observer.observe(el)
}
</script>

<style lang="scss" scoped></style>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值