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里面了

相关推荐
蓝易云1 分钟前
CentOS 7上安装X virtual framebuffer (Xvfb) 的步骤以及如何解决无X服务器的问题
前端·后端·centos
到底起什么网名才能不重名1 分钟前
使用各种CSS美化网页
前端·css·vscode·bootstrap·html
然我2 分钟前
面试必问:JS 事件机制从绑定到委托,一篇吃透所有考点
前端·javascript·面试
小蜜蜂嗡嗡11 分钟前
flutter封装vlcplayer的控制器
前端·javascript·flutter
一tiao咸鱼13 分钟前
如何简单使用 prompt
前端·aigc
cdbqss119 分钟前
VB.net编写的身份证类
前端·.net
骑自行车的码农36 分钟前
React短文系列 遍历fiber树 App的创建
前端·react.js
AskSky40 分钟前
为了搞一个完美的健身APP,我真是费尽心机
前端
斯~内克1 小时前
基于Vue.js和PDF-Lib的条形码生成与批量打印方案
前端·vue.js·pdf
阴阳怪气乌托邦1 小时前
别再啃OA代码了!低代码"搭积木"式搞数智化,我直接少写500行
前端·低代码