$attrs 和 $listeners

一、概念:
$attrs: 包括组件 props 和 emits property 中未包含的所有属性 (例如,class、style、v-on 监听器等) ps: 官网原话
其实就可以简单理解为:除了组件内props声名了的所有给组件传的值(class,style除外)
这个属性有什么作用呢?
当我们需要给多层嵌套父子组件传值,而且杂的时候,可以直接使用它,可以使代码看起来更加简洁。案例如下:

// 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"></m-grandron>
export default {
	props:{
		dataStatus: String,
	},
	data(){
		return {}
	},
	created(){
		console.log('dataStatus',this.dataStatus)  //  123
		console.log('dataMessage',this.dataMessage)  //  456
	}
}
// m-grandron.vue
export default {
	data(){
		return {}
	},
	created(){
		console.log('dataStatus',this.$attrs)  //  {dataMessage:456} 因为child组件中props声名了dataStatus所以这里$attrs就不含有dataStatus
	}
}

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

注意:
当又给m-grandron组件传了和$attrs内属性同名的值时,值会被覆盖(使用传入的值)。 如下:

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

$listeners: 接收除了带有.native事件修饰符的所有事件监听器
作用和上述类同。
有一点不同的是:当出现同名的事件时,不会被覆盖,而是都会执行,执行顺序就是事件冒泡的执行顺序,先触发child 再触发parent
案例如下:

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

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐