vue 3 指令监听 vue 发射

Posted

技术标签:

【中文标题】vue 3 指令监听 vue 发射【英文标题】:vue 3 directives listen vue emit 【发布时间】:2021-02-03 01:52:45 【问题描述】:

我想要实现的是构建一个加载 vue 指令, 带有 v-loading 指令的函数将渲染微调器和阻塞事件,直到函数 promise 解决或拒绝。

到目前为止我所尝试的:

    使用addEventListener,但是只能监听dom的native事件,不能监听vue事件 劫持 vue $emit 函数,但收到警告说不要覆盖名为 $ 的 vue 本机函数,即使此解决方案有效,我认为这是一个糟糕的解决方案。 在指令参数中,binding.instance[binding.value.name] 引用组件中的 onEvent 函数,我尝试覆盖它但它不起作用。当 onEvent 再次触发时,它会在覆盖之前运行旧的 onEvent。 第三方事件发射器(例如,手套)。这种方法效果很好,但是自定义组件必须编写额外的代码来发出事件。 作为下面的示例代码, v-loading 的用户必须记住写 2 个发射(mitt 和 vue 的发射)。 这不是那么直接,而且它有额外的依赖性。
// 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 的原生事件)吗?


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>

【问题讨论】:

【参考方案1】:

Vue 3 文档 recommends 使用外部库,例如 mitttiny-emitter

JSFiddle Example

<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');

【讨论】:

感谢您的回答。我忘了提,我确实找到了第三方手套解决方案。但这不是我想做的完美解决方案,因为它具有第三方依赖性,而且使用起来也不是那么直接,用户必须记住编写 mitt.emit() 以使 v-loading 工作。我已经更新了我的问题。但是,我没有找到任何其他解决方案来收听 vue 的发射。所以,我会先将你的答案标记为正确。 @LHJ 是的,我不确定这是否是 Vue 3 中的回归。我尝试使用 onMountednextTick 在没有 mitt 的情况下实现您想要的结果,但没有成功。 很好的答案,但不幸的是,我们不得不依赖第三方库来完成以前版本中开箱即用的事情。

以上是关于vue 3 指令监听 vue 发射的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Vue 自定义指令中添加事件监听器?

vue基础

68 vue框架-part2 指令操作

Vue (表单斗篷条件循环指令,分隔符成员计算属性成员属性的监听vue组件子组件)

vue - 计算属性监听自定义指令

10《Vue 入门教程》Vue 双向绑定指令