前言:本文介绍封装自定义指令v-login实现,点击某个元素时如果未登录弹出登录框登录,已经登录则执行对应的操作,以及该指令的扩展功能
在Web应用中,某些操作(如关注、收藏等)需要用户登录后才能执行。传统实现方式是在每个需要登录的操作前都添加登录校验逻辑,这会导致:
解决方案:使用Vue自定义指令v-login
统一处理登录校验,让代码更简洁、更专注于业务逻辑。
传统方式 | v-login方式 |
---|---|
每个操作单独校验 | 统一拦截处理 |
代码重复率高 | 逻辑集中管理 |
维护困难 | 修改一处即可全局生效 |
import { useUserStore } from "@/stores/user";
import { ElMessage } from "element-plus";
import type { Component, Directive } from 'vue';
interface DirectiveBinding {
value: Function,
oldValue: Function,
arg: string,
modifiers: Record<string, boolean>,
instance: Component,
dir: Directive
}
const handler = (binding: DirectiveBinding) => {
const fn = binding.value
const userStore = useUserStore()
if (!userStore.isSign) {
// 扩展的未登录处理方式
if (binding.modifiers?.msg) {
ElMessage.error('请先登录')
}
// 弹出登录框
userStore.showLogin = true
return
}
// 已登录执行回调
fn?.()
}
const vLogin: Directive = {
mounted(el, binding) {
if (typeof binding.value !== 'function') return
el.fn = handler.bind(el, binding)
el.addEventListener('click', el.fn)
},
unmounted(el, binding) {
if (typeof binding.value !== 'function') return
el.removeEventListener('click', el.fn)
}
}
export default vLogin
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useUserStore = defineStore('user', () => {
const showLogin = ref(false)
const isSign = ref(false)
return {
isSign,
showLogin
}
})
<template>
<ElDialog v-model="visible" v-bind="dialogAttributes">
<div class="login-box">
<h1>这是一个登录框</h1>
</div>
</ElDialog>
</template>
<script setup>
import { useWsLoginStore } from '@/stores/ws.ts'
import { computed } from 'vue'
const loginStore = useWsLoginStore()
const visible = computed({
get() {
return loginStore.showLogin
},
set(value) {
loginStore.showLogin = value
}
})
const dialogAttributes = {
'close-on-click-modal': false,
width: '376',
top: '7vh',
center: true
}
</script>
import { createApp } from 'vue'
import vLogin from '@/directives/v-login'
const app = createApp(App)
app.directive("login", vLogin)
<template>
<button v-login="handleSecureAction">需要登录的操作</button>
</template>
<script setup>
const handleSecureAction = () => {
console.log('用户已登录,执行安全操作')
}
</script>
带提示的登录校验
<button v-login.msg="handleSecureAction">带提示的登录操作</button>
自定义未登录处理
const handler = (binding: DirectiveBinding) => {
// ...原有逻辑
if (!userStore.isSign) {
// 自定义处理逻辑
if (binding.arg === 'custom') {
return customLoginHandler()
}
// ...默认处理
}
}
if (binding.modifiers?.admin && !userStore.isAdmin) {
ElMessage.error('需要管理员权限')
return
}
性能优化:对于频繁点击的元素,考虑添加防抖处理
多框架适配:封装为独立npm包,支持React等框架
测试覆盖:确保指令在各种边界条件下的稳定性
v-login指令通过Vue的自定义指令机制,优雅地解决了登录校验的代码冗余问题。它的优势在于:
未来可考虑: