$attrs
如果向一个子组件传递数据attribute时,该子组件并没有相应prop定义的attribute时。这些 attribute 会被添加到这个组件的根元素上。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| //父组件 <template> <div class="home"> 以下为组件S1的内容 <S1 :foo='foo' :eoo='eoo'/> </div> </template> ... import S1 from '@/components/S1.vue' data(){ return{ foo:'I am foo', eoo:'I am eoo', } }, components:{ S1 }, ...
|
1 2 3 4 5 6 7 8 9 10 11 12
| //子组件 S1 <template> <div> {{foo}} </div> </template> ... data(){ return{} }, props:['foo'], ...
|
我们可以看到只有foo才会显示,而eoo则被添加到根元素中了,即便页面添加了
也不会显示的。
如果不希望组件的根元素继承 attribute
,你可以在组件的选项中设置 inheritAttrs: false
。再配合实例的 $attrs
property 使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| //修改后的子组件S1,添加$attrs,并查看其值 <template> <div> <p>foo:{{foo}}</p> <p>attrs:{{$attrs}}</p> </div> </template> ... data(){ return{} }, props:['foo'], inheritAttrs: false, ...
|
我们可以看到在组件的选项中设置 inheritAttrs: false
后,组件没有相应prop定义的attribute将会被绑定到$attrs
上。
通过对象取值的方法是行不通的,比如$attrs.eoo
,但是我们可以通过v-bind="$attrs"
传入其内部组件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| //修改后的子组件S1,引入子组件S1Child <template> <div> <p>foo:{{foo}}</p> <p>attrs:{{$attrs}}</p> 以下为组件S1Child的内容 <s1-child v-bind="$attrs"></s1-child> </div> </template> ... import S1Child from '@/components/S1Child.vue' data(){ return{} }, components:{ S1Child, }, props:['foo'], inheritAttrs: false, ... //子组件S1Child <template> <div> <p>eoo:{{eoo}}</p> </div> </template> ... props:['eoo'], ...
|
我们可以看到,通过$attrs
可以接收组件没有相应prop定义的attribute,并通过prop
让其子子组件接收到。那么组件S1Child
的信息怎么传递给其父父组件呐?$listeners
。
$listeners
包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners"
传入内部组件——在创建更高层次的组件时非常有用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| //修改后的父组件,添加绑定事件@upData <template> <div class="home"> 以下为组件S1的内容 <S1 :foo='foo' :eoo='eoo' @upData="getS1ChidData"/> </div> </template> ... import S1 from '@/components/S1.vue' data(){ return{ foo:'I am foo', eoo:'I am eoo', } }, components:{ S1 }, methods:{ getS1ChidData(value){ console.log('这是组件S1Chid传过来的数据:',value) } } ...
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| //修改后的子组件S1,绑定$listeners <template> <div> <p>foo:{{foo}}</p> <p>attrs:{{$attrs}}</p> 以下为组件S1Child的内容 <s1-child v-bind="$attrs" v-on="$listeners"></s1-child> </div> </template> ... import S1Child from '@/components/S1Child.vue' data(){ return{} }, components:{ S1Child, }, props:['foo'], inheritAttrs: false, ... //子组件S1Child <template> <div> <p>eoo:{{eoo}}</p> <button @click="startUpData">upData</button> </div> </template> ... props:['eoo'], methods:{ startUpData(){ this.$emit('upData','我是S1Child传过来的数据!') } } ...
|
通过点击组件S1Child中的按钮触发当前实例上的upData
事件,但是并不能直接触发非父组件的upData
事件,需要通过v-on="$listeners"
也就通过$listeners
接收了父组件的事件监听器并传给内部组件。