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原生特性,所以没显示在下图中
![100%](/posts/3873/1639717574033-bc4d7fa7-1a3e-42aa-b9e5-291a977cc74b.png)
我们可以验证下标题的结论:
MySelector.vue
1 | <template> |
![100%](/posts/3873/1639717555407-bdf98009-f37e-4f57-97e8-5134050bf6f6.png)
现在父组件给子组件绑定事件、而子组件不 $emit
App.vue
1 | <template> |
![100%](/posts/3873/1639717734168-79cb4dd6-4d7d-496a-bc43-74a2221ebf8c.png)
禁用子组件的根组件的继承
MySelector.vue
1 | <template> |
这样标签就不会继承属性了,切换selector也没法触发事件:
![100%](/posts/3873/1639717889677-eee6ee8a-1021-4a12-9a7c-f8ae222d0432.png)
但是 this.$attrs
依然有值:
![100%](/posts/3873/1639717925512-b2e9fdd8-0159-4fc6-af18-044530646bc6.png)
如果我们此时手动给 select
标签绑定 $attrs
(平铺属性),就又能继承了(事件也能生效):
1 | <template> |
![100%](/posts/3873/1639718022178-213769f3-562e-4328-ab73-60c3734c3465.png)
什么情况下需要禁止继承(input 的 autofocus)
想要实现让子组件 input 聚焦:
LoginBox.vue
1 | <template> |
App.vue
1 | <template> |
我们会发现 input 并没有聚焦,而是把 autofocus 属性设置给了组件的根元素 div:
![100%](/posts/3873/1639718378090-4312e150-03e6-4ad9-b3c4-74d77eed4974.png)
此时我们就需要禁止默认继承来达到目的:
1 | <template> |
![100%](/posts/3873/1639718481993-531ceadc-1713-475b-a003-7f5eff9a9d7d.png)
多个根组件选择性传递 $attrs
App.vue
1 | <template> |
MyList.vue
- 只有
v-if="item.isSubscribable"
为真,才会给 li 元素绑定上v-bind="$attrs"
- 否则就不会把父组件的
@click="bookSubscribe"
绑定到 li 元素上去
1 | <template> |