1、问题背景
我想要实现当单击按钮的时候,根据设置片段该按钮是否需要用户登录,如果用户未登录的话,需要登录
这其中有一个点就是,如果token失效,我会使用refreshtoken来重新获取,也就有了问题描述中的在directive中使用useFetch的操作
这个是我的按钮的写法
<div v-needs-check="{ needValidate: true }" class="animation-follow-btn no-animation" @click="test()">
<div class="follow-ctx show">
关注
</div>
</div>
其中用到的是这个:v-needs-check="{ needValidate: true }"
我的redirective的写法是
// plugins/directives.js
export default defineNuxtPlugin((nuxtApp) => {
// 自定义指令:需要登录校验
nuxtApp.vueApp.directive('needs-check', {
mounted(el, binding) {
const onClick = async (event) => {
const { needValidate = true } = binding.value || {}
var isNeedLogin = false;
//当前缓存的用户信息
const customerStore = websiteStore.customerStore();
//这里进行过期的判断
..........
if (needValidate && isNeedLogin) {
// 阻止默认行为
event.stopImmediatePropagation();
event.preventDefault();
event.stopPropagation();
websiteStore.customerStore().showLoginModal = true;//显示登录对话框
return false
}
}
el.addEventListener('click', onClick, true)
// 保存引用以便更新
el._needsCheckClick = onClick
},
unmounted(el) {
el.removeEventListener('click', el._needsCheckClick, true)
}
})
})
2、问题1-已补执行问题
首先我这边的useFetch一开始由于没有使用await,导致了异步执行的情况下,对于是否登录状态的判断有问题,这个好改,加上await相关的就可以了
3、问题2-click方法阻断问题(这个问题最终没有解决)
解决了异步问题,加下来的诉求就是我需要在directive阻断click方法的执行,只有当验证登录信息通过之后,才会继续执行click方法的函数
这里我用的是event.stopImmediatePropagation();
我在实际执行过程中发现,是不生效的
在我的调试过程中发现,如果我把useFetch相关的代码注释掉,则方法阻断是正常的,但是加上之后,阻断方法就失效了
查了下ai,发现在directive中使用useFetch是有问题的:
这是一个非常关键的提示 —— 说明你正在尝试在 Vue 的自定义指令(directive)中使用组合式 API(如 useFetch)
,而这在 Vue 的设计中是 不支持的。
🔴 核心问题:useFetch
不能在 directive 中使用
useFetch
是 Vue 3 组合式 API(Composition API)中的一个组合函数(composable),它依赖于组件的 setup 上下文。- 而 自定义指令(directive)是普通的 JavaScript 对象,没有
setup()
上下文,因此不能直接使用 useFetch、ref、reactive 等组合式 API
。 - 如果你在 directive 中强行调用
useFetch
,会抛出错误,或导致行为异常(比如事件监听失效、无法阻止 click 等)。
4、解决方法
我这里其实就是直接去掉了useFetch的处理。同时,登录接口中我同时返回了token和refreshtoken的过期时间
我在directive中只是做了时间的判断,如果两个时间同时过期的状态,才弹出登录页。
不再进行refreshtoken置换token的操作了
相当于在功能上是变相的妥协