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

Vue3升级中多Emits重复定义触发TS1117错误的解决方法

解决方案

错误原因

你触发的An object literal cannot have multiple properties with the same name.ts(1117)错误,本质是JavaScript/TypeScript的对象不允许重复定义同名属性——你在defineComponent的配置对象里写了两次emits和两次setup,这违反了对象的语法规则。

具体修复步骤

  1. 合并自定义事件声明:把所有需要触发的自定义事件名放在同一个emits数组中,不要拆分多次声明。
  2. 合并setup逻辑:将两个setup函数里的方法和逻辑合并到同一个setup中,通过emit统一触发事件。
  3. 修正响应式变量:showDeleteAddressConfirmation需要声明为响应式变量,Vue3中可以用ref实现。
  4. 统一代码风格:尽量避免选项式API(methods、props等)和组合式API(setup)混用,推荐使用更简洁的<script setup>语法。

修复后的代码示例

这里用Vue3推荐的<script setup lang="ts">语法改写,逻辑更清晰:

<script setup lang="ts">
import { ref } from 'vue';
import { DataTableActionTypes } from '@/shared/enums/dataTableActionTypes.enum';
import Modal from '@/shared/components/modal/Modal.vue';

// 声明组件接收的props
interface Props {
  item?: any; // 对应原Vue2的any类型
}
const props = defineProps<Props>();

// 声明组件触发的自定义事件
interface Emits {
  (e: 'action', data: any, type: DataTableActionTypes): void;
  (e: 'delete-address', id: number, type: DataTableActionTypes): void;
}
const emit = defineEmits<Emits>();

// 响应式变量
const showDeleteAddressConfirmation = ref(false);

// 事件处理方法
const onDeleteAddressClick = () => {
  showDeleteAddressConfirmation.value = true;
  emit('action', props.item, DataTableActionTypes.ActionButtonSelect);
};

const onCloseDelete = () => {
  showDeleteAddressConfirmation.value = false;
  emit('action', props.item, DataTableActionTypes.ResetActionButtton);
};

const deleteAddress = () => {
  showDeleteAddressConfirmation.value = false;
  emit('delete-address', props.item, DataTableActionTypes.Delete);
};
</script>

如果你更倾向于保留选项式API的写法,修复后的代码如下:

<script lang="ts">
import { defineComponent, ref } from 'vue';
import { DataTableActionTypes } from '@/shared/enums/dataTableActionTypes.enum';
import Modal from '@/shared/components/modal/Modal.vue';

export default defineComponent({
  name: 'AddressListActionButtons',
  components: {
    Modal
  },
  props: {
    item: {
      type: Object as () => any, // 声明any类型的正确方式
      default: null
    }
  },
  // 合并后的自定义事件声明
  emits: ['action', 'delete-address'],
  setup(props, { emit }) {
    const showDeleteAddressConfirmation = ref(false);

    const onAction = (data: any, type: DataTableActionTypes) => {
      emit('action', data, type);
    };

    const onDeleteAddress = (id: number, type: DataTableActionTypes) => {
      emit('delete-address', id, type);
    };

    // 将方法和响应式变量暴露给模板
    return {
      showDeleteAddressConfirmation,
      onAction,
      onDeleteAddress
    };
  },
  methods: {
    onDeleteAddressClick() {
      this.showDeleteAddressConfirmation = true;
      this.onAction(this.item, DataTableActionTypes.ActionButtonSelect);
    },
    onCloseDelete() {
      this.showDeleteAddressConfirmation = false;
      this.onAction(this.item, DataTableActionTypes.ResetActionButtton);
    },
    deleteAddress() {
      this.showDeleteAddressConfirmation = false;
      this.onDeleteAddress(this.item, DataTableActionTypes.Delete);
    }
  }
});
</script>

关键说明

  • 选项式API中,props的type不能直接写undefined,如果要表示任意类型,用Object as () => any或者直接any。
  • 组合式API中,defineProps和defineEmits是Vue3提供的编译器宏,不需要导入就能使用,用于类型安全地声明props和事件。
  • 无论哪种写法,同一个配置对象里不能重复定义同名属性,这是JS/TS的基础语法规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 19:23:27