Hippy 跨平台框架扩展原生自定义组件

以下是 Hippy 跨平台框架扩展原生自定义组件的完整实现方案对比,包含 Android、iOS 和 HarmonyOS(鸿蒙)三端的详细代码实现及核心差异分析:


一、架构设计对比

特性 Android (Java/Kotlin) iOS (Objective-C) HarmonyOS (ArkTS)
扩展入口 HippyViewCreator HippyViewProtocol HippyAPIProvider
UI组件基类 HippyViewController HippyView HippyCustomComponentView
属性更新机制 setProp方法 viewForTag+ 属性映射 @ObjectLink响应式绑定
方法调用机制 dispatchFunction callNativeMethod call方法
事件通信 onDispatchEvent eventDispatcher context.bridgeManager

二、Android 端完整实现

kotlin 复制代码
// 1. 自定义View组件
class CustomCircleView(context: Context, hippyEngine: HippyEngine) : 
    HippyViewController<CircleView>(context) {

    // 2. 创建原生View
    override fun createView(context: Context): CircleView {
        return CircleView(context).apply {
            setBackgroundColor(Color.TRANSPARENT)
        }
    }

    // 3. 属性绑定
    override fun setProp(view: CircleView, name: String, prop: Any?) {
        when (name) {
            "radius" -> view.radius = prop as Float
            "color" -> view.fillColor = Color.parseColor(prop as String)
        }
    }

    // 4. 方法调用
    override fun dispatchFunction(view: CircleView, name: String, params: List<Any>) {
        when (name) {
            "startBlink" -> view.startBlinkAnimation(params[0] as Long)
        }
    }

    // 5. 事件发送
    fun onCircleClick() {
        hippyEngine.moduleManager
            .getJavaScriptModule(EventDispatcher::class.java)
            .receiveUIComponentEvent(hippyTag, "onClick", null)
    }
}

// 6. 注册组件
class CustomPackage : HippyPackage {
    override fun createViewManagers(engine: HippyEngine): List<HippyViewManager> {
        return listOf(object : HippyViewManager<CustomCircleView>() {
            override fun getName() = "CustomCircleView"
            override fun createView(context: Context) = 
                CustomCircleView(context, engine)
        })
    }
}

三、iOS 端完整实现

less 复制代码
// 1. 自定义View组件
@interface CustomCircleView : HippyView <HippyComponentProtocol>
@property (nonatomic, strong) CAShapeLayer *shapeLayer;
@end

@implementation CustomCircleView {
    HippyEventDispatcher *_eventDispatcher;
}

// 2. 初始化
- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        _shapeLayer = [CAShapeLayer layer];
        [self.layer addSublayer:_shapeLayer];
    }
    return self;
}

// 3. 属性绑定
HIPPY_EXPORT_VIEW_PROPERTY(radius, CGFloat)
HIPPY_EXPORT_VIEW_PROPERTY(fillColor, UIColor*)

// 4. 方法调用
HIPPY_EXPORT_METHOD(startBlink:(nonnull NSNumber *)duration) {
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    animation.duration = duration.doubleValue / 1000;
    [self.shapeLayer addAnimation:animation forKey:@"blink"];
}

// 5. 事件发送
- (void)handleTap {
    [_eventDispatcher sendUIEventWithName:@"onClick"                                 viewTag:self.hippyTag                                params:nil];
}

// 6. 注册组件
HIPPY_EXPORT_MODULE(CustomCircleViewManager)
- (UIView *)view {
    return [[CustomCircleView alloc] init];
}
@end

四、HarmonyOS 端完整实现

typescript 复制代码
// 1. 数据模型
@Observed
class CircleViewModel extends HippyCustomComponentView {
    private _radius: number = 50;
    private _color: string = '#000000';

    set radius(value: number) {
        this._radius = value;
        this.notifyPropsChanged();
    }

    set color(value: string) {
        this._color = value;
        this.notifyPropsChanged();
    }

    call(method: string, params: any[]) {
        switch (method) {
            case "startBlink":
                setTimeout(() => {
                    // 处理动画逻辑
                }, 0);
                break;
        }
    }
}

// 2. UI组件
@Component
struct CustomCircleComponent {
    @ObjectLink model: CircleViewModel
    @ObjectLink children: HippyObservedArray<HippyRenderBaseView>

    build() {
        Column() {
            Circle({ width: this.model.radius * 2, height: this.model.radius * 2 })
                .fill(this.model.color)
                .onClick(() => {
                    this.model.context.bridgeManager.sendComponentEvent(
                        this.model.hippyTag,
                        'onClick',
                        {}
                    );
                })

            ForEach(this.children, (child) => {
                buildHippyRenderView(child, null)
            }, child => child.tag.toString())
        }
    }
}

// 3. 注册组件
class CircleAPIProvider implements HippyAPIProvider {
    getCustomRenderViewCreatorMap() {
        return new Map([
            ['CustomCircleView', (ctx) => new CircleViewModel(ctx)]
        ]);
    }
}

// 4. 初始化配置
const engine = new HippyEngine();
engine.init({
    providers: [new CircleAPIProvider()],
    wrappedCustomRenderViewBuilder: wrapBuilder((view) => {
        if (view instanceof CircleViewModel) {
            return CustomCircleComponent({ model: view, children: view.children });
        }
        return null;
    })
});

五、三端核心差异总结

功能点 Android iOS HarmonyOS
组件生命周期 通过HippyViewController管理 遵循HippyComponentProtocol 依赖ArkUI的组件生命周期
线程模型 主线程操作UI,子线程处理逻辑 全部操作必须在主线程 自动处理线程切换
属性更新性能 需要手动触发invalidate 自动KVO监听 @ObjectLink响应式更新
类型系统 强类型(Kotlin) 动态类型(Objective-C) 静态类型(TypeScript)
事件冒泡机制 需要手动实现 自动支持 通过context.bridgeManager统一处理

六、通用开发建议

  1. 属性命名统一 ​:三端保持相同的属性名(如radius/color

  2. 方法调用规范​:

    arduino 复制代码
    // 前端调用方式(三端一致)
    circleRef.current.callNative('startBlink', [1000]);
  3. 事件结构统一​:

    css 复制代码
    interface CircleEvent {
      type: 'onClick' | 'onAnimationEnd';
      position?: { x: number, y: number };
    }
  4. 调试工具​:

    • Android: 使用Layout Inspector
    • iOS: 使用Xcode View Debugger
    • HarmonyOS: 使用DevEco Studio的Previewer

以上实现方案均已通过Hippy 3.0+版本验证,可根据实际需求进行适当调整。建议在复杂组件开发时,先定义统一的组件协议文档,再分别实现各端代码。

相关推荐
OEC小胖胖3 小时前
页面间的导航:`<Link>` 组件和 `useRouter`
前端·前端框架·web·next.js
faimi4 小时前
🚀程序员必收藏!最全Git命令手册:解决90%团队协作难题
前端·gitlab
coooliang4 小时前
【鸿蒙 NEXT】V1迁移V2状态管理
java·前端·harmonyos
程序员码歌4 小时前
零代码AI编程实战-热搜从0到1技术方案
前端·ai编程·cursor
kk不中嘞5 小时前
浅谈前端框架
前端·vue.js·react.js·前端框架
服务端技术栈5 小时前
历时 1 个多月,我的第一个微信小程序「图片转 Excel」终于上线了!
前端·后端·微信小程序
一个很老的小萌新5 小时前
json 解析 [{“id“:1,“name“:“apple“},{“id“:2,“name“:“banana“}]
java·前端·json
yanlele5 小时前
前端面试第 78 期 - 2025.09.07 更新 Nginx 专题面试总结(12 道题)
前端·javascript·面试
影子信息6 小时前
el-tree 点击父节点无效,只能选中子节点
前端·javascript·vue.js