this ,因为
this 是一个代理对象。现在貌似看上去没什么问题了,不过我们还忘记了一件事儿,即
scopedSlots ,不过
scopedSlots 与
slot 的实现机制不一样,本质上
scopedSlots 就是一个接收数据作为参数并渲染
VNode 的函数,所以不存在
context 的概念,所以直接透传即可:hoc.js
function WithConsole (WrappedComponent) {
return {
mounted () {
console.log('I have already mounted')
},
props: WrappedComponent.props,
render (h) {
const slots = Object.keys(this.$slots)
.reduce((arr, key) => arr.concat(this.$slots[key]), [])
.map(vnode => {
vnode.context = this._self
return vnode
}) return h(WrappedComponent, {
on: this.$listeners,
props: this.$props,
// 透传 scopedSlots
scopedSlots: this.$scopedSlots,
attrs: this.$attrs
}, slots)
}
}
}
到现在为止,一个高阶组件应该具备的基本功能算是实现了,但这仅仅是个开始,要实现一个完整健壮的
Vue 高阶组件,还要考虑很多内容,比如:函数式组件中要使用
render 函数的第二个参数代替
this 。以上我们只讨论了以纯对象形式存在的
Vue 组件,然而除了纯对象外还可以函数。创建
render 函数的很多步骤都可以进行封装。处理更多高阶函数组件本身的选项(
而不仅仅是上面例子中的一个简单的生命周期钩子 )我觉得需要放上两个关于高阶组件的参考链接,供参考交流:
Discussion: Best way to create a HOC
https://github.com/jackmellis/vue-hoc
为什么在 Vue 中实现高阶组件比较难
前面说过要分析一下为什么在
Vue 中实现高阶组件比较复杂而
React 比较简单。这主要是二者的设计思想和设计目标不同,在
React 中写组件就是在写函数,函数拥有的功能组件都有。而
Vue 更像是高度封装的函数,在更高的层面
Vue 能够让你轻松的完成一些事情,但与高度的封装相对的就是损失一定的灵活,你需要按照一定规则才能使系统更好的运行。










