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

解决Vue中eslint-plugin-vue报错:v-slot指令需属于自定义元素

问题根源

ESLint的vue/no-invalid-v-slot规则报错,是因为它检测到你在原生<slot>元素的内容里使用了v-slot语法,而规则要求v-slot必须挂载在自定义元素上,原生<slot>不满足这个条件。

解决方法

方法一:调整模板结构(推荐)

#save-template这类模板本质是属于<DxPopup>的,不是<slot>的子内容,把模板移到<DxPopup>的直接子级位置即可:

<template>
  <DxPopup
    v-bind="$attrs"
    :hide-on-outside-click="true"
    :drag-enabled="true"
    :wrapper-attr="popupAttributes"
    position="center"
    v-on="$listeners"
    @hiding="onHiding"
  >
    <slot />
    <slot name="footer">
      <DxToolbarItem template="save-template" toolbar="bottom" location="after" />
      <DxToolbarItem template="cancel-template" toolbar="bottom" location="after" />
    </slot>

    <!-- 模板作为DxPopup的直接子元素 -->
    <template #save-template>
      <DxButton text="Ok" @click="onOk" />
    </template>

    <template #cancel-template>
      <DxButton text="Cancel" @click="onCancel" />
    </template>
  </DxPopup>
</template>

这样既符合Vue插槽规范,能通过ESLint检测,DevExtreme的模板功能也能正常运行。

方法二:禁用ESLint对应规则

如果不想修改结构,用注释临时忽略当前代码的规则检查:

<slot name="footer">
  <DxToolbarItem template="save-template" toolbar="bottom" location="after" />
  <!-- eslint-disable-next-line vue/no-invalid-v-slot -->
  <template #save-template>
    <DxButton text="Ok" @click="onOk" />
  </template>

  <DxToolbarItem template="cancel-template" toolbar="bottom" location="after" />
  <!-- eslint-disable-next-line vue/no-invalid-v-slot -->
  <template #cancel-template>
    <DxButton text="Cancel" @click="onCancel" />
  </template>
</slot>

也可以在项目的ESLint配置文件(比如.eslintrc.js)里全局修改规则,允许在<slot>内使用v-slot:

module.exports = {
  // 其他配置...
  rules: {
    // 其他规则...
    'vue/no-invalid-v-slot': ['error', {
      allowModifiers: true,
      slotProps: ['slot']
    }]
  }
}

另外,你之前用<custom-element>包裹模板的做法不可行,因为这个元素没有在Vue中注册,直接删除即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 11:20:39