Appearance
封装鉴权按钮组件/指令
页面中有很多按钮都需要用户登录才能使用的,如果给每个按钮的点击事件添加判断登录的逻辑多少有点繁琐,所以就想自己封装一个鉴权组件。最开始想用自定义指令实现的,奈何自定义指令没办法捕获点击事件。
通过组件
原理:鉴权按钮组件其实没有按钮,通过 slots 传入对应的按钮组件,外层一个 div 容器,当点击插槽中的内容时,事件触发会从 html 根元素开始捕获,会经过外层的 div,最后到达插槽里面的元素,我们可以通过事件捕获机制来拦截到此次点击事件,并执行对应鉴权逻辑,最后(最关键的是)通过 stopImmediatePropagation,停止事件捕获,也就是说停止浏览器向里面寻找事件触发的元素,和停止事件冒泡一个逻辑,只是方向不一样,冒泡是从里到外,捕获是从外到内。
vue
<template>
<div
@click.capture="(e) => onHandleClick(e)"
class="auth-btn-container">
<slot name="default"></slot>
</div>
</template>
<script lang="ts" setup>
// hooks
import useUserStore from "@/store/user";
import { useMessage } from "naive-ui";
// types
import type { VNode } from "vue";
// configs
import tips from "@/config/tips";
const message = useMessage();
const userStore = useUserStore();
/**
* 点击的该容器的回调 在捕获时触发
*/
const onHandleClick = (e: Event) => {
if (userStore.isLogin) {
message.success("用户登录了");
} else {
message.warning("未登录");
// 停止事件捕获 阻止继续事件捕获
e.stopImmediatePropagation();
}
};
defineSlots<{
default: () => VNode[];
}>();
</script>
<template>
<div
@click.capture="(e) => onHandleClick(e)"
class="auth-btn-container">
<slot name="default"></slot>
</div>
</template>
<script lang="ts" setup>
// hooks
import useUserStore from "@/store/user";
import { useMessage } from "naive-ui";
// types
import type { VNode } from "vue";
// configs
import tips from "@/config/tips";
const message = useMessage();
const userStore = useUserStore();
/**
* 点击的该容器的回调 在捕获时触发
*/
const onHandleClick = (e: Event) => {
if (userStore.isLogin) {
message.success("用户登录了");
} else {
message.warning("未登录");
// 停止事件捕获 阻止继续事件捕获
e.stopImmediatePropagation();
}
};
defineSlots<{
default: () => VNode[];
}>();
</script>
通过自定义指令
基本思路就是通过自定义指令可以在 mounted 配置项中可以获取绑定的 DOM 元素,可以给他绑定点击事件,该事件在捕获时触发。 在点击事件回调中可以对身份进行鉴权,通过就允许事件的执行,未通过不允许事件继续执行。