attributes的传递与继承
- 传递给子组件的属性,如果不被子组件的
props
显示声明,都会存放进子组件的this.$attrs
中- 直接给子组件传递事件,就能被父组件监听到,不需要通过子组件
$emit
触发
- 直接给子组件传递事件,就能被父组件监听到,不需要通过子组件
常规父传子,父监听子组件方案
App.vue
1 | <template> |
MySelector.vue
1 | <template> |
attributes 方案
单个根元素的组件,使用组件传值的所有属性,都会增加到子组件的根元素上
我们删除父组件的自定义事件绑定以及子组件的
emit监听,只传值:
App.vue
1 | <template> |
MySelector.vue
1 | <template> |
我们此刻会发现,页面上默认vue就帮我们把父传子的值传过来了,而且给组件 <my-selector>
绑定的 model 属性,也自动传给了组件内部的 select
标签:
- value是select原生特性,所以没显示在下图中
我们可以验证下标题的结论:
MySelector.vue
1 | <template> |
现在父组件给子组件绑定事件、而子组件不 $emit
App.vue
1 | <template> |
禁用子组件的根组件的继承
MySelector.vue
1 | <template> |
这样标签就不会继承属性了,切换selector也没法触发事件:
但是 this.$attrs
依然有值:
如果我们此时手动给 select
标签绑定 $attrs
(平铺属性),就又能继承了(事件也能生效):
1 | <template> |
什么情况下需要禁止继承(input 的 autofocus)
想要实现让子组件 input 聚焦:
LoginBox.vue
1 | <template> |
App.vue
1 | <template> |
我们会发现 input 并没有聚焦,而是把 autofocus 属性设置给了组件的根元素 div:
此时我们就需要禁止默认继承来达到目的:
1 | <template> |
多个根组件选择性传递 $attrs
App.vue
1 | <template> |
MyList.vue
- 只有
v-if="item.isSubscribable"
为真,才会给 li 元素绑定上v-bind="$attrs"
- 否则就不会把父组件的
@click="bookSubscribe"
绑定到 li 元素上去
1 | <template> |