💂 个人网站: 【紫陌】【笔记分享网】
💅 想寻找共同学习交流、共同成长的伙伴, 请点击【前端学习交流群】
组件通信-$attrs与$listeners
1.$attrs
父子组件通信的一种
$attrs与$listeners ---- 父子组件通信
$attrs:组件实例的属性,可以获取到父亲传递的props数据(前提子组件没有通过props接受)
$listeners:组件实例的属性,可以获取到父亲传递自定义事件(对象形式呈现)
看例子:
在element UI的button按钮上二次封装给他加上一个hover提示的按钮,
子组件:
<template>
<div>
<el-button></el-button>
</div>
</template>
el-button里面我们什么都没写,原因是为了引入的是一个动态的,以后我们修改按钮的内容,页面按钮样式,或者icon会动态改变
父组件:
<template>
<div>
<h2>自定义带Hover提示的按钮</h2>
<HintButton/>
</div>
</template>
<script type="text/ecmascript-6">
import HintButton from './HintButton';
export default {
name: 'AttrsListenersTest',
***ponents:{
HintButton
},
}
</script>
目前效果:
$attrs的使用
然后在父组件传递props数据给子组件
修改父组件:
type="su***ess" icon="el-icon-plus"这是element的
title是自己定义的,这些都是props,
<template>
<div>
<h2>自定义带Hover提示的按钮</h2>
<HintButton type="su***ess" icon="el-icon-plus" title="我是紫陌"/>
</div>
</template>
<script type="text/ecmascript-6">
import HintButton from './HintButton';
export default {
name: 'AttrsListenersTest',
***ponents:{
HintButton
},
}
</script>
这回我们子组件接收父组件传递过来的参数,我们就不用props了,我们利用组件实例身上的一个属性$attrs也可以接收父组件传递给子组件的数据
注意:要是我们用props接受的话,父组件给的数据子组件通过props接收的属性,在$attrs属性当中是获取不到的
修改子组件:
<template>
<div>
<!-- 可以巧妙利用a标签实现按钮带有的提示功能 -->
<a :title="title">
<!--
这是复杂写法,也可以实现效果,但是属性多的话就很麻烦
<el-button :type="$attrs.type" :icon="$attrs.icon" :size="$attrs.size">添加</el-button>
-->
<!-- 下面这种写法v-bind不能用:简写 不然没有效果,这就是简单的写法效果-->
<el-button v-bind="$attrs">添加</el-button>
</a>
</div>
</template>
<script>
export default {
name: "",
props:['title'],
mounted(){
//this.$attrs:可以获取到父亲传递的数据【props】
//this.$attrs是可以获取父亲传递的props数据,如果子组件通过
//props:[],接受的属性,this.$attrs属性是获取不到的
console.log(this.$attrs);
}
};
</script>
子组件中打印一下$attrs
$attrs:组件实例的属性,可以获取到父亲传递的props数据(前提子组件没有通过props接受)
上面用了props接受父组件title,打印的$attrs就没有title这个属性了。不用props接受就能在$attrs获取的到。
一开始我的需求:需要封装ElementUI按钮,并且是带Hover提示的按钮,我们在el-button外面来一个a标签,因为a标签有一个title属性,就带有提示功能。现在就可以通过这个完成了。
2.$listeners地使用
这个时候我们想给按钮绑定一个点击事件,点击弹出一个999什么的,我们知道HintButton是一个组件,在组件身上写@click他就变成了自定义事件了
@click.native其实是可以解决的,但是我们这里有另外的解决办法,所以我这样来演示:
父组件:
在组件标签上绑定一个自定义事件。点击组件的时候弹出999
<template>
<div>
<h2>自定义带Hover提示的按钮</h2>
<!-- 二次封装的HintButton按钮的时候,把人家el-button需要的数据传递过去 -->
<HintButton type="su***ess" icon="el-icon-plus" title="我是紫陌" @click="handler"/>
</div>
</template>
<script type="text/ecmascript-6">
import HintButton from './HintButton';
export default {
name: 'AttrsListenersTest',
***ponents:{
HintButton
},
methods: {
handler() {
alert('999');
},
},
}
</script>
我们想给HintButton绑定单击事件 实际上是给el-button绑定单击事件
我们先看看$listeners身上有没有父组件传递过来的自定义事件,并且利用v-on来给el-button绑定单击事件
子组件中:
<template>
<div>
<!-- 可以巧妙利用a标签实现按钮带有的提示功能 -->
<a :title="title">
<!--
这是复杂写法,也可以实现效果,但是属性多的话就很麻烦
<el-button :type="$attrs.type" :icon="$attrs.icon" :size="$attrs.size">添加</el-button>
-->
<!-- 下面这种写法v-bind不能用:简写 不然没有效果,这就是简单的写法效果-->
<el-button v-bind="$attrs" v-on="$listeners">添加</el-button>
</a>
</div>
</template>
<script>
export default {
name: "",
props:['title'],
mounted(){
//this.$attrs:可以获取到父亲传递的数据【props】
//this.$attrs是可以获取父亲传递的props数据,如果子组件通过
//props:[],接受的属性,this.$attrs属性是获取不到的
console.log(this.$attrs);
// $listeners他也是组件实例自身上的一个属性,他可以获取到父组件给子组件传递的自定义事件。
console.log(this.$listeners);
}
};
</script>
打印结果:
最后一个就是打印事件
此时点击按钮就可以弹出999了
总结:
$listeners与$attrs(组件通信方式的一种)
他们两者都是组件实例的属性,可以获取到父组件给子组件传递的props与自定义事件