使用 Vue3 开发 Dropdown 组件的几个核心要点

2,401 阅读2分钟

这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战

Dropdown 组件大家并不陌生,在操作项比较多的情况下,通常会使用这个组件归纳到一起,鼠标点一下,诶,展开菜单。如果自己一步步实现 Dropdown 组件,需要攻克那些难关呢?这篇文章将着重介绍几个核心要点。

组件结构选择

假设自定义组件的外层组件为bp-dropdown,那么大致可以采用两种结构,一种是将菜单选项也封装成组件并嵌套到bp-dropdown中,大致形式如下:

<bp-dropdown @change="onChange" title="操作">
	 <bp-dropdown-option value="add">新增</bp-dropdown-option>
	 <bp-dropdown-option value="edit">编辑</bp-dropdown-option>
</bp-dropdown>

第二种是不采用组件包裹的形式,将菜单选项统一放到bp-dropdown的属性中,并在组件中进行遍历渲染。示例:

<bp-dropdown :options="basicOptions" @change="onChange">
	操作
</bp-dropdown>

const basicOptions = [
	{ label: "新增", value: "add" },
	{ label: "编辑", value: "edit" },
];

触发方式

一般来说支持点击触发就够了,但是为了体验考虑,以及特殊的使用场景,还是需要做鼠标移入(hover)触发的。具体配置:

const triggerList = ["click", "hover"]; // 可用触发方式
props: {
    trigger: {
      type: String,
      default: "click",
      validator: (value) => triggerList.indexOf(value) !== -1,
    }, // 触发方式
},

具体的触发实现

const optionShow = ref(false);

const onClick = () => {
	if (props.trigger === "hover") return;
	optionShow.value ? onClose() : onOpen();
};

const onMouseEnter = () => {
	if (props.trigger === "click") return;
	onOpen();
};
const onMouseLeave = () => {
	if (props.trigger === "click") return;
	onClose();
};

点击元素外部触发事件

实现点击外部元素触发通常采用指令封装的形式,Vue2 和 Vue3 的自定义指令实现有稍微的不太一样,在这里不一一赘诉,直接提供点击外部元素触发的指令代码:

export const clickOutside = {
  // 初始化事件
  beforeMount(el, binding, vnode) {
    function handleClick(e) {
      // 如果为元素本身,则返回
      if (el.contains(e.target) || e.target.className.includes(binding.arg)) {
        return false;
      }
      // 如果绑定了函数,则返回执行
      binding.value(e);
    }
    el.__vueClickOutside__ = handleClick;
    document.addEventListener('click', handleClick);
  },
  // 解除事件监听
  unmounted(el, binding) {
    document.removeEventListener('click', el.__vueClickOutside__);
    delete el.__vueClickOutside__;
  },
};

使用示例:

import { clickOutside } from "../directives.js";

export default {
	directives: { clickOutside },
}

欢迎阅读其它文章