vite 脚手架使用教程(五)-自定义directive

1,288 阅读2分钟

这是我参与「掘金日新计划 · 8 月更文挑战」的第8天,点击查看活动详情

vite 脚手架使用教程(一)-新建项目

vite 脚手架使用教程(二)-vue-router使用

vite 脚手架使用教程(三)-Pinia的使用&环境配置

vite 脚手架使用教程(四)- NaiveUI 的安装

建议按序观看

Vue 也允许注册自定义指令。注意代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。

在 src 目录下,新建directive目录,在目录中

├── drag
│   └── index.ts
├── index.ts
├── permission
│   └── index.ts
└── typinng.ts

自定义指令插件封装

directive/index.ts

import { App } from 'vue'
import drag from './drag/index'

const install = (app: App): void => {
  app.directive('drag', drag)
  //...等等可配置
}

export default install

配置类型

typinng.ts

export interface IDirectiveOptionsWithInstall extends ObjectDirective {
  install?: (app: App) => void
}

drag移动指令的配置

/**
 * @description: drag移动指令
 * @param {HTMLElement} el
 * @param {DirectiveBinding} binding
 * @return {*}
 */
const drag = (el: HTMLElement) => {
  const odiv: HTMLElement = el // 获取当前元素

  odiv.onmousedown = (e) => {
    // 算出鼠标相对元素的位置
    const disX = e.clientX - odiv.offsetLeft
    const disY = e.clientY - odiv.offsetTop

    document.onmousemove = (e) => {
      // 用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
      let left = e.clientX - disX
      let bottom = document.body.offsetHeight - (e.clientY - disY) - odiv.clientHeight
      if (left < 0) left = 0

      if (left > document.body.offsetWidth - odiv.offsetWidth) {
        left = document.body.offsetWidth - odiv.offsetWidth
      }

      if (bottom < 0) {
        bottom = 0
      }

      if (bottom > document.body.offsetHeight - odiv.offsetHeight) {
        bottom = document.body.offsetHeight - odiv.offsetHeight
      }

      // 移动当前元素
      odiv.style.left = left + 'px'
      odiv.style.bottom = bottom + 'px'
    }
    document.onmouseup = () => {
      document.onmousemove = null
      document.onmouseup = null
    }
  }
}

const plugin = (el: HTMLElement) => {
  drag(el)
}

export default plugin as IDirectiveOptionsWithInstall

权限指令

// 是否有权限
export function isAuthor(id: number | number[] | undefined): boolean {
  if (id === undefined) {
    return false;
  }
  let groups = [];
  if (userModule.userInfo) {
    // 这里要和状态管理一起用,按照当前的后端接口设计
    groups = userModule.userInfo.permid || []; 
  }
  let show: boolean = false;
  if (typeof id === 'number') {
    id = [id];
  }
  groups &&
    groups.forEach((item: number) => {
      if ((id as number[]).includes(item)) {
        show = true;
      }
    });
  return show;
}

/**
 * @description: 权限指令
 * @param {HTMLElement} el
 * @param {DirectiveBinding} binding
 * @return {*}
 */
const checkPermission = (el: HTMLElement, binding: DirectiveBinding) => {
  const { value } = binding
  const id: number = binding.value ? binding.value : 0;
    const show: boolean = isAuthor(id);
    // 如果是 hide,就直接移除 dom
    if ('hide' in binding.modifiers || !Object.keys(binding.modifiers).length     {
      !show && el.parentNode && el.parentNode.removeChild(el);
    }
    // 如果是disabled,就给当前标签,添加上disabled的属性
    if ('disabled' in binding.modifiers) {
      !show && el.setAttribute('disabled', 'true');
      !show && el.classList.add('is-disabled');
    }
}

const plugin = (el: HTMLElement, binding: DirectiveBinding) => {
  checkPermission(el, binding)
}

// modifiers 特殊修饰符
// v-premiss.hide
// v-premiss.disabled