探索Vue高阶组件的使用(5)
上面的代码中,我们将模板改写成了渲染函数,看上去没什么问题,实则不然,上面的代码中 WrappedComponent
组件依然收不到 props
,有的同学可能会问了,我们不是已经在 h
函数的第二个参数中将 attrs
传递过去了吗,怎么还收不到?当然收不到, attrs
指的是那些没有被声明为 props
的属性,所以在渲染函数中还需要添加 props
参数:
hoc.js
export default function WithConsole (WrappedComponent) { return { mounted () { console.log('I have already mounted') }, render (h) { return h(WrappedComponent, { on: this.$listeners, attrs: this.$attrs, props: this.$props }) } } }
那这样是不是可以了呢?依然不行,因为 this.$props
始终是空对象,这是因为这里的 this.$props
指的是高阶组件接收到的 props
,而高阶组件没有声明任何 props
,所以 this.$props
自然是空对象啦,那怎么办呢?很简单只需要将高阶组件的 props
设置与被包装组件的 props
相同即可了:
hoc.js
export default function WithConsole (WrappedComponent) { return { mounted () { console.log('I have already mounted') }, props: WrappedComponent.props, render (h) { return h(WrappedComponent, { on: this.$listeners, attrs: this.$attrs, props: this.$props }) } } }
现在才是一个稍微完整可用的高阶组件。大家注意用词: 稍微
,纳尼?都修改成这样了还不行吗?当然,上面的高阶组件能完成以下工作:
1、透传 props
2、透传没有被声明为 props
的属性
3、透传事件
大家不觉得缺少点儿什么吗?我们前面说过,一个 Vue
组件的三个重要因素: props
、 事件
以及 slots
,前两个都搞定了,但 slots
还不行。我们修改 BaseComponent
组件为其添加一个具名插槽和默认插槽,如下:
base-component.vue
<template> <div> <span @click="handleClick">props: {{test}}</span> <slot name="slot1"/> <!-- 具名插槽 --> <p>===========</p> <slot/> <!-- 默认插槽 --> </div> </template> <script> export default { ... } </script>
然后我们写下如下测试代码:
<template> <div> <base-component> <h2 slot="slot1">BaseComponent slot</h2> <p>default slot</p> </base-component> <enhanced-com> <h2 slot="slot1">EnhancedComponent slot</h2> <p>default slot</p> </enhanced-com> </div> </template> <script> import BaseComponent from './base-component.vue' import hoc from './hoc.js' const EnhancedCom = hoc(BaseComponent) export default { components: { BaseComponent, EnhancedCom } } </script>
内容版权声明:除非注明,否则皆为本站原创文章。