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
相关产品推荐
相关产品推荐

