Vue 中 $attrs 与 $listeners

我们知道,向子组件传递数据,是通过 v-bind 子类组件定义的 props 属性完成的,这只适用于单向、两层组件之间。同样地,事件传递也是在父组件中用 v-on 给子组件绑定事件,然后在子组件中通过 this.$emit 触发的、以达到修改父组件数据的目的。

那么,在多层嵌套组件中,顶层组件和最底层组件之间如何进行数据传递和事件触发呢?比如,A 组件引用了 B 组件,而 B 组件又引用了 C 组件,那么怎么在 A 中将数据传给 C ;在 C 中,怎么触发 A 中的方法呢?这就是 $attrs$listeners 的作用了。

1.$attrs

继承所有的父组件属性(没有通过 props 接收的属性还有 class 类名 和 style 样式 )。

javascript 复制代码
// parent.vue
<m-child :data-status="dataStatus" :data-message="dataMessage"></m-child>

export default {
	data(){
		return {
			dataStatus: '123',
			dataMessage: '456'
		}
	}
}
// m-child.vue
<m-grandron v-bind="$attrs" data-message="789"></m-grandron>
export default {
	props:{
		dataStatus: String,
	},
	created(){
		console.log('dataStatus',this.dataStatus)  //  123
		console.log('dataMessage',this.dataStatus)  //  456
	}
}
// m-grandron.vue
export default {
	created(){
		console.log('dataStatus',this.$attrs)  
// 因为child组件中props声名了dataStatus所以这里$attrs就不含有dataStatus
// 因为传的dataMessage和$attrs内同名,所以值被覆盖变为789 
	}
}

如果我们按常规的props传值,就要一层一层传,层级多了就很恶心,使用$attrs就很轻松的做到了。

2.$listeners

它是一个对象,能接收所有的方法绑定,里面包含了作用在这个组件上的所有监听器,配合 v-on="$listeners" 将所有的事件监听器指向这个组件的某个特定的子元素。

有一点不同的是:当出现同名的事件时,不会被覆盖,而是都会执行,执行顺序就是事件冒泡的执行顺序,先触发child 再触发parent\

typescript 复制代码
// parent.vue
<m-child @customEvent="ev_customEvent"></m-child>

export default {
	data(){
		return {
			dataStatus: '123',
			dataMessage: '456'
		}
	},
	methods:{
		ev_customEvent(){
			console.log('my name is parent!')
		}
	}
}
// m-child.vue
<m-grandron v-on="$listeners" @customEvent="ev_customEvent"></m-grandron>
export default {
	props:{
		dataStatus: String,
	},
	data(){
		return {}
	},
	methods:{
		ev_customEvent(){
			console.log('my name is child!')
		}
	}
}
// m-grandron.vue
<button @click="$emit('customEvent')">click me!</button>
export default {
	data(){
		return {}
	},
}


// 控制台
// my name is child!
// my name is parent!

使用$listeners 属性可以很方便的在层级很深的组件内,立马就修改最外层的父组件内的属性值

注意:在vue3.0 中$listeners被移除了,将所有属性都集合到attrs里面了

相关推荐
半生过往30 分钟前
2025 前端动效实战指南:Vue Bits & React Bits 深度拆解(功能 / 复用 / 高频问题处理)
前端·vue.js·react.js
程序员包打听33 分钟前
Vitest 4.0 重磅发布:Browser Mode 正式稳定,前端测试进入新纪元
前端
BumBle34 分钟前
UniApp 多页面编译优化:编译时间从10分钟到1分钟
前端
星链引擎37 分钟前
大语言模型的技术突破与稳定 API 生态的构建
前端
还是大剑师兰特37 分钟前
TypeScript 面试题及详细答案 100题 (71-80)-- 模块与命名空间
前端·javascript·typescript
BumBle38 分钟前
使用 SortableJS 实现vue3 + Element Plus 表格拖拽排序
前端·vue.js·element
玉宇夕落38 分钟前
HTML5 音乐敲击乐静态界面
前端
海在掘金6112738 分钟前
告别"拼写错误":TS如何让你的代码"字字精准"
前端
用户479492835691539 分钟前
什么是XSS攻击,怎么预防,一篇文章带你搞清楚
前端·javascript·安全
摸着石头过河的石头40 分钟前
深入理解JavaScript事件流:从DOM0到DOM3的演进之路
前端·javascript·性能优化