这是我参与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 },
}