vue render函数开发高阶组件(HOC)
以下是使用 Vue Render 函数开发高阶组件(HOC)的完整指南,包含 6 种典型场景的实现示例:
一、基础 HOC 架构
const withEnhancement = (WrappedComponent) => {
return {
name: `HOC-${WrappedComponent.name}`,
props: WrappedComponent.props, // 透传 props
render(h) {
// 增强逻辑
const newProps = {
...this.$props,
extraProp: '增强属性'
}
return h(WrappedComponent, {
props: newProps,
on: this.$listeners,
scopedSlots: this.$scopedSlots,
attrs: this.$attrs
}, this.$slots.default)
}
}
}
二、典型场景实现
1. 属性增强 HOC
// 自动添加 loading 状态
const withLoading = (WrappedComponent) => {
return {
data() {
return { isLoading: false }
},
methods: {
showLoader() { this.isLoading = true },
hideLoader() { this.isLoading = false }
},
render(h) {
return h('div', [
h(WrappedComponent, {
props: {
...this.$props,
loading: this.isLoading
},
on: {
...this.$listeners,
submit: () => {
this.showLoader()
this.$emit('submit')
}
}
}),
this.isLoading && h('div', { class: 'loader' }, '加载中...')
])
}
}
}
2. 生命周期拦截 HOC
// 组件挂载/更新日志
const withLogger = (WrappedComponent) => {
return {
mounted() {
console.log(`组件 ${WrappedComponent.name} 已挂载`)
},
updated() {
console.log(`组件 ${WrappedComponent.name} 已更新`)
},
render(h) {
return h(WrappedComponent, {
props: this.$props,
on: this.$listeners,
attrs: this.$attrs
})
}
}
}
3. 条件渲染 HOC
// 权限控制
const withAuth = (WrappedComponent) => {
return {
computed: {
hasPermission() {
return checkUserPermission(this.$props.requiredRole)
}
},
render(h) {
return this.hasPermission
? h(WrappedComponent, {
props: this.$props,
attrs: this.$attrs
})
: h('div', { class: 'no-permission' }, '无权限访问')
}
}
}
4. 样式增强 HOC
// 添加公共样式
const withStyle = (WrappedComponent, style) => {
return {
render(h) {
return h('div', {
style: {
border: '1px solid #eee',
padding: '10px',
...style
}
}, [
h(WrappedComponent, {
props: this.$props,
on: this.$listeners
})
])
}
}
}
5. 状态管理 HOC
// 提供全局状态
const withStore = (WrappedComponent) => {
return {
inject: ['store'],
render(h) {
return h(WrappedComponent, {
props: {
...this.$props,
store: this.store
}
})
}
}
}
6. 组合式 HOC
// 组合多个 HOC
const composeHOCs = (...hocs) => (WrappedComponent) => {
return hocs.reduceRight((acc, hoc) => hoc(acc), WrappedComponent)
}
// 使用示例
const EnhancedComponent = composeHOCs(
withLogger,
withLoading,
withStyle({ backgroundColor: '#f5f5f5' })
)(BaseComponent)
三、高级技巧
1. 插槽透传
render(h) {
return h(WrappedComponent, {
scopedSlots: Object.keys(this.$scopedSlots).reduce((slots, name) => {
slots[name] = props => this.$scopedSlots[name](props)
return slots
}, {})
}, this.$slots.default)
}
2. Ref 转发
render(h) {
return h(WrappedComponent, {
ref: 'wrappedComponent',
props: this.$props
})
},
methods: {
getWrappedInstance() {
return this.$refs.wrappedComponent
}
}
3. 动态组件名
const createDynamicHOC = (componentName) => {
return {
render(h) {
return h(componentName, {
props: this.$props
})
}
}
}
四、最佳实践
- 属性合并策略
// 合并默认属性
const mergedProps = {
...WrappedComponent.props,
...this.$props
}
- 事件监听合并
const mergedListeners = {
...WrappedComponent.options.listeners,
...this.$listeners
}
- 生命周期管理
// 继承原始生命周期
const originalMounted = WrappedComponent.options.mounted
export default {
mounted() {
originalMounted && originalMounted.call(this)
// 新增逻辑
}
}
五、HOC 工厂模式
const createHOCFactory = (options) => {
return (WrappedComponent) => {
return {
mixins: [options.mixins],
render(h) {
return h('div', { class: options.wrapperClass }, [
h(WrappedComponent, {
props: {
...this.$props,
...options.extraProps
}
})
])
}
}
}
}
// 使用工厂
const createRedBorderHOC = createHOCFactory({
wrapperClass: 'red-border',
extraProps: { borderSize: 2 }
})
六、调试技巧
- 显示组件层级
render(h) {
const vnode = h(WrappedComponent, /* ... */)
console.log('Rendered VNode:', vnode)
return vnode
}
- HOC 标识
name: `HOC(${getDisplayName(WrappedComponent)})`,
function getDisplayName(WrappedComponent) {
return WrappedComponent.name || 'AnonymousComponent'
}
通过以上模式,可以创建出功能强大的高阶组件,这些组件具备以下优势:
- 逻辑复用:封装通用逻辑(如权限校验、日志记录)
- 动态增强:运行时动态修改组件行为
- 组合能力:通过组合多个 HOC 实现复杂功能
- 无侵入性:不影响原始组件内部实现
- 类型安全(配合 TypeScript):可维护性更强
实际应用场景包括:
- 全局 loading 状态管理
- 表单自动校验
- 组件埋点系统
- 主题样式注入
- 权限控制体系
- 性能优化(如缓存)