docs/development/native-event.md
当终端网络切换,或者横竖屏改变的时候,终端需要像前端发送一些全局的广播事件,这样前端可以根据不同的状态来控制业务状态。
Hippy中的事件分为两种类型:UI组件(component)事件与模块(module)事件
UI组件事件由Dom层负责处理,Native层需要先将事件封装为DomEvent类型,然后通过DomNode::HandleEvent(const std::shared_ptr<DomEvent>& event)方法发送。
Hippy UI事件流程符合W3C标准
1.首先构建出HippyValue对象
HippyValue是对Hippy事件数据的封装,包括以下类型:
2.通过HippyValue构建出DomEvent对象。
DomEvent用于封装UI事件
//DomEvent部分重要属性以及方法
class DomEvent {
public:
DomEvent(std::string type, std::weak_ptr<DomNode> target, bool can_capture, bool can_bubble, std::shared_ptr<HippyValue> value)
: type_(std::move(type)),
target_(target),
current_target_(target),
prevent_capture_(false),
prevent_bubble_(false),
can_capture_(can_capture),
can_bubble_(can_bubble),
value_(value) {}
DomEvent(std::string type, std::weak_ptr<DomNode> target, bool can_capture = false, bool can_bubble = false)
: DomEvent(std::move(type), target, can_capture, can_bubble, nullptr) {}
DomEvent(std::string type, std::weak_ptr<DomNode> target, std::shared_ptr<HippyValue> value)
: DomEvent(std::move(type), target, false, false, value) {}
private:
std::string type_;
std::weak_ptr<DomNode> target_;
std::weak_ptr<DomNode> current_target_;
bool prevent_capture_;
bool prevent_bubble_;
bool can_capture_;
bool can_bubble_;
EventPhase event_phase_ = EventPhase::kNone;
std::shared_ptr<HippyValue> value_;
};
DomEvent对象主要有以下属性:
click,longclick,touchstart默认情况下,UI组件预定义了一下事件名称
constexpr char kClickEvent[] = "click";
constexpr char kLongClickEvent[] = "longclick";
constexpr char kTouchStartEvent[] = "touchstart";
constexpr char kTouchMoveEvent[] = "touchmove";
constexpr char kTouchEndEvent[] = "touchend";
constexpr char kPressIn[] = "pressin";
constexpr char kPressOut[] = "pressout";
constexpr char kTouchCancelEvent[] = "touchcancel";
constexpr char kLayoutEvent[] = "layout";
constexpr char kShowEvent[] = "show";
constexpr char kDismissEvent[] = "dismiss";
3.将事件发送给driver层
auto event = std::make_shared<DomEvent>("click", node, false, false, hippyValue);
node->HandleEvent(event);
业务端通过UI组件绑定事件即可向dom层注册UI事件
//react
<View
onClick={(event) => {
console.log('click style outer', event.target.nodeId, event.currentTarget.nodeId);
// return false means trigger bubble
return false;
}}>
</View>
//vue
<div class="toolbar" @click="onClickHandler">
</div>
我们支持Android、iOS、Flutter的事件通讯:
当终端网络切换,或者横竖屏改变的时候,终端需要向前端发送一些全局的广播事件,这样前端可以根据不同的状态来控制业务状态。
终端在需要发送事件的地方调用代码:
HippyMap hippyMap = new HippyMap();
hippyMap.pushString("result", "hello i am from native");
hippyEngine.sendEvent("rotate", hippyMap);
终端在需要发送事件的地方调用代码:
// 调用HippyBridge的如下实例方法,比如:
[self.hippyBridge sendEvent:@"rotate" params:@{@"foo":@"bar"}];
/// Send native event to JS side
/// - Parameters:
/// - eventName: event name
/// - params: event info
- (void)sendEvent:(NSString *)eventName params:(NSDictionary *_Nullable)params;
鸿蒙平台接口和安卓相似。
终端在需要发送事件的地方调用代码:
const map = new Map();
map.pushString("result", "hello i am from native");
hippyEngine.sendEvent("rotate", map);
var params = VoltronMap();
params.push<String>("result", "hello i am from native");
// 这里的 context 是 EngineContext,在 module 中可以直接获取到
context
.moduleManager
.getJavaScriptModule<EventDispatcher>(enumValueToString(JavaScriptModuleType.EventDispatcher))
?.receiveNativeEvent("rotate", params);
当浏览器加载结束或者使用了一些三方库完成一些功能后需要向业务侧抛出事件。
WebRenderer 在需要发送事件的地方调用以下代码:
发送事件,HippyWebModule 基类提供的 context 提供了向业务层发送事件的能力
const eventName = '自定义名字';
const param = {};
context.sendEvent(eventName, param);
发送事件,HippyWebView 基类的 context 提供了向业务层发送事件的能力
const eventName = '自定义名字';
const param = {};
context.sendEvent(eventName, param);
发送事件,Hippy.web.engine 的 context 提供了向业务层发送事件的能力
const engine = Hippy.web.engine;
const eventName = '自定义名字';
const param = {};
engine.context.sendEvent(eventName, param);