You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue中事件发射器注销与GISWSCaller类封装及调用问询

问题解答

一、当前unregisterEvtEmitter写法是否正确?事件发射器的正确注销方式

当前写法完全不正确,你只是把计算属性的值设为undefined,根本没有实现事件发射器的注销逻辑。

首先明确核心逻辑:你当前用的是Vue组件的defineEmits定义的组件事件,这类事件的监听由父组件完成,子组件仅负责触发(emit)。针对"注销"需求,分两种场景处理:

1. 父组件取消监听子组件事件

父组件可通过动态绑定v-on或组件实例的$off方法(Vue2)取消监听;Vue3 <script setup>中,需通过ref获取子组件实例后调用对应方法。

2. 子组件内部清理事件相关资源

如果需求是子组件停止触发事件、清理异步请求或状态,正确做法是:

  • 取消正在进行的异步请求(用AbortController)
  • 清理存储的参数和结果状态

修正后的示例代码:

// 新增请求控制器用于取消异步请求
const abortController = ref(null);

// 修改事件触发逻辑,加入请求取消机制
const emit = defineEmits({
  evtRunWSRouteTest: async (params) => {
    // 先取消未完成的请求
    if (abortController.value) abortController.value.abort();
    abortController.value = new AbortController();
    
    const splitted = params.split(',');
    if (splitted.length === 4) {
      try {
        const response = await fetch(`https://xx/xx/getDistanceFromOriginToDestination/${params}`, {
          signal: abortController.value.signal
        });
        res.value = await response.json();
        return res.value;
      } catch (err) {
        // 忽略请求取消的报错
        if (err.name !== 'AbortError') {
          console.error('请求失败', err);
          return false;
        }
      }
    }
    return false;
  }
});

// 正确的注销函数
function unregisterEvtEmitter() {
  // 取消请求
  if (abortController.value) abortController.value.abort();
  // 清理状态
  params = null;
  res.value = null;
}

如果是使用自定义事件发射器(如Node.js events模块或第三方库mitt),注销需调用发射器的off方法移除对应监听:

// 示例:用mitt实现自定义事件发射器
import mitt from 'mitt';
const emitter = mitt();

// 监听事件
emitter.on('evtRunWSRouteTest', handler);

// 注销事件监听
function unregisterEvtEmitter() {
  emitter.off('evtRunWSRouteTest', handler);
  // 或清空所有监听
  // emitter.all.clear();
}

二、封装为GISWSCaller类并导出,Vue文件中的调用方式

1. 封装GISWSCaller类

创建GISWSCaller.js文件:

import { ref, computed } from 'vue';

export class GISWSCaller {
  constructor() {
    this.res = ref(null);
    this.params = ref(null);
    this.abortController = null;
    // 若需自定义事件发射器,可引入mitt
    // import mitt from 'mitt';
    // this.emitter = mitt();
  }

  // 计算属性,用于触发请求
  get evtEmitterParamsCompProperties() {
    return computed({
      get: () => this.params.value,
      set: (newValue) => this.runRouteTest(newValue)
    });
  }

  // 执行路由测试请求
  async runRouteTest(params) {
    // 取消之前的请求
    if (this.abortController) this.abortController.abort();
    this.abortController = new AbortController();
    
    this.params.value = params;
    const splitted = params.split(',');
    if (splitted.length === 4) {
      try {
        const response = await fetch(`https://xx/xx/getDistanceFromOriginToDestination/${params}`, {
          signal: this.abortController.signal
        });
        this.res.value = await response.json();
        // 若用自定义事件发射器,触发事件
        // this.emitter.emit('evtRunWSRouteTest', this.res.value);
        return this.res.value;
      } catch (err) {
        if (err.name !== 'AbortError') {
          console.error('请求失败', err);
          return false;
        }
      }
    }
    return false;
  }

  // 注销/清理资源
  unregisterEvtEmitter() {
    // 取消请求
    if (this.abortController) this.abortController.abort();
    // 清理状态
    this.params.value = null;
    this.res.value = null;
    // 若用自定义事件发射器,清空监听
    // this.emitter.all.clear();
  }
}

2. 在Vue组件中调用类实例

修改Vue组件代码:

<template>
  <div class="container">
    <button @click="handleRouteTest">routTest</button>
    result:{{ caller.res }}
  </div>
</template>

<script setup>
import { GISWSCaller } from './GISWSCaller.js';
import { onUnmounted } from 'vue';

// 创建类实例
const caller = new GISWSCaller();

// 触发路由测试
function handleRouteTest() {
  const param = '30.976639,30.056021,30.97775,30.033333';
  // 方式1:直接调用请求方法
  caller.runRouteTest(param);
  // 方式2:通过计算属性设置值触发请求
  // caller.evtEmitterParamsCompProperties.value = param;
}

// 组件卸载时自动清理资源
onUnmounted(() => {
  caller.unregisterEvtEmitter();
});
</script>

补充说明

  • 封装类后,所有状态和方法都聚合在类内部,更易于复用和维护;
  • 若使用自定义事件发射器,Vue组件可通过类实例的emitter.on监听事件,emitter.off取消监听。

内容的提问来源于stack exchange,提问作者Amrmsmb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 11:17:41