我想要实现的是构建一个加载vue指令,
带有 v-loading 指令的函数将渲染微调器并阻止事件,直到函数 promise 解析或拒绝。
到目前为止我尝试过的:
- 使用addEventListener,但只能监听dom的原生事件,不能监听vue事件
- 劫持 vue $emit 函数,但收到警告说不要覆盖名为 $ 的 vue 原生函数,即使这个解决方案有效,我认为这是一个糟糕的解决方案。
- 在指令参数中,绑定(bind).实例[绑定(bind).值.名称]引用组件中的onEvent函数,我尝试覆盖它但它不起作用。当 onEvent 再次触发时,它会运行覆盖之前的旧 onEvent。
- 第三方事件发射器(例如,mitt)。这种方法效果很好,但是自定义组件必须编写额外的代码来发出事件。
如下面的示例代码,
v-loading的用户必须记住写2个emit(mitt和vue的emit)。
它并不是那么简单,而且它有额外的依赖性。
// mitt solution
// custom-component template
<custom-component v-loading:event="onEvent">
// custom-component script
setup(props, {emit}) {
function emitEvent() {
emit("event");
// bad: have to remember to write this extra line, and it is third party dependency
mittEmitter.emit("event");
}
}
那么,还有其他解决方案可以从 vue 的 $emit 监听 vue 的事件(不是 dom 的 native 事件)吗?
LoadingDirective.ts
import { Directive } from "vue";
const Loading: Directive = {
mounted(el, binding) {
const eventName = binding.arg;
const onEvent = binding.value;
// I want to listen vue's event(eventName) here
// do something extra
onEvent(); // original onEvent() function to run in App.vue
// do something extra
}
};
export default Loading;
App.vue
<template>
<!-- when onEvent triggered, a spinner will be render in custom-component -->
<custom-component v-loading:event="onEvent" />
</template>
CustomComponent.vue
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
setup(props, {emit}) {
function emitEvent() {
// use only vue's emit
emit("event")
}
return {
onEvent
};
}
});
</script>
最佳答案
Vue 3 文档 recommends使用外部库,例如 mitt
或 tiny-emitter
。
<template>
<div id="app">
<custom-component v-loading="eventHandler" />
</div>
</template>
const emitter = mitt();
const customComponent = { template: '<h1>Example</h1>' };
const app = Vue.createApp({
components: { customComponent },
setup() {
setTimeout(() => {
emitter.emit('loadingEvent', { colour: 'Green' });
}, 1000);
const eventHandler = e => console.log('Handled!', e);
return { eventHandler };
},
});
app.directive('loading', {
mounted(el, binding) {
const func = binding.value;
emitter.on('loadingEvent', data => {
// your logic here...
func(data);
});
},
});
app.mount('#app');
关于vue.js - vue 3指令监听vue发出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64441717/