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

Vue3如何传递全部$attrs给子组件但排除事件监听器?

解决Vue3中$attrs传递监听器引发的重复触发问题

方案1:Setup内过滤后传递(推荐)

利用Vue3的useAttrs()钩子获取attrs对象,直接过滤掉以on开头的事件监听器属性,再传递给子组件,同时设置inheritAttrs: false避免自动挂载到根元素:

<script setup>
import { useAttrs } from 'vue'

const attrs = useAttrs()
// 过滤事件监听器,保留普通属性
const plainAttrs = Object.fromEntries(
  Object.entries(attrs).filter(([key]) => !key.startsWith('on'))
)
</script>

<template>
  <child v-bind="plainAttrs" />
</template>

<script>
// 关闭自动挂载attrs到根元素
export default {
  inheritAttrs: false
}
</script>

方案2:全局复用过滤逻辑

如果多个组件需要该逻辑,封装全局工具函数减少重复代码:

// src/utils/attrsHelper.js
export function filterOutListeners(attrs) {
  return Object.fromEntries(
    Object.entries(attrs).filter(([key]) => !key.startsWith('on'))
  )
}

在组件中调用:

<script setup>
import { useAttrs } from 'vue'
import { filterOutListeners } from '@/utils/attrsHelper'

const attrs = useAttrs()
const plainAttrs = filterOutListeners(attrs)
</script>

<template>
  <child v-bind="plainAttrs" />
</template>

<script>
export default {
  inheritAttrs: false
}
</script>

方案3:模板内直接处理(适合简单场景)

无需额外脚本,直接在模板中通过对象过滤传递属性:

<template>
  <child 
    v-bind="Object.fromEntries(Object.entries($attrs).filter(([key]) => !key.startsWith('on')))"
  />
</template>

<script>
export default {
  inheritAttrs: false
}
</script>

补充说明

  • 若子组件通过defineProps声明了接收的属性,$attrs只会包含未被声明的属性,此时过滤逻辑依然生效。
  • 始终保持inheritAttrs: false,避免Vue自动将未处理的attrs挂载到组件根元素上,引发不必要的DOM属性渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 18:12:18