<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>
渲染结果如下:

上图中蓝色框是
BaseComponent 组件渲染的内容,是正常的。红色框是高阶组件渲染的内容,可以发现无论是具名插槽还是默认插槽全部丢失。其原因很简单,就是因为我们在高阶组件中没有将分发的插槽内容透传给被包装组件(
WrappedComponent ),所以我们尝试着修改高阶组件:hoc.js
function WithConsole (WrappedComponent) {
return {
mounted () {
console.log('I have already mounted')
},
props: WrappedComponent.props,
render (h) { // 将 this.$slots 格式化为数组,因为 h 函数第三个参数是子节点,是一个数组
const slots = Object.keys(this.$slots)
.reduce((arr, key) => arr.concat(this.$slots[key]), [])
return h(WrappedComponent, {
on: this.$listeners,
attrs: this.$attrs,
props: this.$props
}, slots) // 将 slots 作为 h 函数的第三个参数
}
}
}
好啦,大功告成刷新页面,如下:

纳尼:scream:?我们发现,分发的内容确实是渲染出来了,不过貌似顺序不太对。。。。。。蓝色框是正常的,在具名插槽与默认插槽的中间是有分界线(
=========== )的,而红色框中所有的插槽全部渲染到了分界线(
=========== )的下面,看上去貌似具名插槽也被作为默认插槽处理了。这到底是怎么回事呢?想弄清楚这个问题,就回到了文章开始时我提到的一点,即你需要对
Vue 的实现原理有所了解才行,否则无解。接下来就从原理触发讲解如何解决这个问题。这个问题的根源在于:
Vue 在处理具名插槽的时候会考虑作用域的因素 。不明白没关系,我们一点点分析。首先补充一个提示:
会把模板( Vue
)编译成渲染函数(
template










