mirror of
https://github.com/Tencent/Hippy.git
synced 2026-10-29 14:10:47 +08:00
feat(hippy-react): change event capture handle
This commit is contained in:
@@ -142,12 +142,15 @@ new Hippy({
|
||||
|
||||
## 事件捕获
|
||||
|
||||
> 最低支持版本 2.11.2
|
||||
> 最低支持版本 2.11.5
|
||||
|
||||
[[事件捕获范例]](//github.com/Tencent/Hippy/tree/master/examples/hippy-react-demo/src/components/ListView)
|
||||
|
||||
点击事件和触屏事件支持事件捕获,如需注册捕获阶段的事件处理函数,则应在目标元素事件名添加 `Capture` 后缀,如 `onClickCapture`、`onTouchDownCapture`。如果目标元素没有`Capture`
|
||||
事件处理函数,默认不开启捕获。事件捕获会有一定性能损耗,如非必要尽量不开启。
|
||||
点击事件和触屏事件支持事件捕获,如需注册捕获阶段的事件处理函数,则应在目标元素事件名添加 `Capture` 后缀,如 `onClickCapture`、`onTouchDownCapture`。
|
||||
|
||||
Hippy为了做更好的性能优化,如果目标元素没有 `Capture` 事件处理函数,默认不开启捕获,全局冒泡配置 `bubbles: false` 不会影响捕获开启。事件捕获设计与 Web 标准一致,当在任意一个捕获函数内调用 `stopPropagation` 时,会同时阻止剩余的捕获阶段、目标节点阶段和冒泡阶段执行。
|
||||
|
||||
!> 事件捕获会有一定性能损耗,如非必要尽量不开启。
|
||||
|
||||
例子如下:
|
||||
|
||||
@@ -159,14 +162,17 @@ render()
|
||||
onClick={() => {
|
||||
console.log("根节点 点击");
|
||||
}}
|
||||
onClickCapture={() => console.log("根节点 捕获点击")}
|
||||
onClickCapture={(event) => {
|
||||
// 如果根节点调用 stopPropagation,则按钮2的 onClickCapture 和按钮1的 onClick 都不会触发
|
||||
// event.stopPropagation();
|
||||
console.log("根节点 捕获点击")
|
||||
}}
|
||||
>
|
||||
<Text style={{width: 150, height: 100, backgroundColor: "#FF0000"}}
|
||||
onClick={() => {
|
||||
// 点击按钮1不会触发根节点捕获点击
|
||||
console.log("按钮1 点击")
|
||||
}}
|
||||
|
||||
>
|
||||
点击按钮1
|
||||
</Text>
|
||||
|
||||
@@ -216,6 +216,14 @@ export default class ListExample extends React.Component {
|
||||
}
|
||||
return (
|
||||
<View style={styles.container}
|
||||
onClickCapture={(event) => {
|
||||
console.log('onClickCapture style outer', event.target.nodeId, event.currentTarget.nodeId);
|
||||
}}
|
||||
onTouchDown={(event) => {
|
||||
// outer onTouchDown would not be called, because style1 invoked event.stopPropagation();
|
||||
console.log('onTouchDown style outer', event.target.nodeId, event.currentTarget.nodeId);
|
||||
return false;
|
||||
}}
|
||||
onClick={(event) => {
|
||||
console.log('click style outer', event.target.nodeId, event.currentTarget.nodeId);
|
||||
// return false means trigger bubble
|
||||
@@ -252,12 +260,15 @@ export default class ListExample extends React.Component {
|
||||
console.log('onTouchDown ListView', event.target.nodeId, event.currentTarget.nodeId);
|
||||
}}
|
||||
onClickCapture={(event) => {
|
||||
// if calling capture event stopPropagation in one of node,
|
||||
// all capture phase left, target phase and bubbling phase would stop.
|
||||
// event.stopPropagation();
|
||||
console.log('onClickCapture listview', event.target.nodeId, event.currentTarget.nodeId);
|
||||
}}
|
||||
onClick={(event) => {
|
||||
console.log('click listview', event.target.nodeId, event.currentTarget.nodeId);
|
||||
// return false means trigger bubble
|
||||
return false;
|
||||
return true;
|
||||
}}
|
||||
bounces={true}
|
||||
overScrollEnabled={true}
|
||||
|
||||
@@ -141,10 +141,14 @@ function doCaptureAndBubbleLoop(originalEventName: string, nativeEvent: NativeEv
|
||||
currentTarget: getElementFromFiber(nextNodeItem),
|
||||
});
|
||||
}
|
||||
nextNodeItem = nextNodeItem.return;
|
||||
while (nextNodeItem && !isHostComponent(nextNodeItem.tag)) {
|
||||
// only handle HostComponent
|
||||
if (eventQueue.length === 0) {
|
||||
nextNodeItem = null;
|
||||
} else {
|
||||
nextNodeItem = nextNodeItem.return;
|
||||
while (nextNodeItem && !isHostComponent(nextNodeItem.tag)) {
|
||||
// only handle HostComponent
|
||||
nextNodeItem = nextNodeItem.return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (eventQueue.length > 0) {
|
||||
@@ -156,8 +160,13 @@ function doCaptureAndBubbleLoop(originalEventName: string, nativeEvent: NativeEv
|
||||
const { eventName, currentTarget: currentTargetNode, listener, isCapture } = listenerObj;
|
||||
const syntheticEvent = new Event(eventName, currentTargetNode, targetNode);
|
||||
Object.assign(syntheticEvent, nativeEvent);
|
||||
// whether it is capture or bubbling event, returning false or calling stopPropagation would both stop phase
|
||||
if (isCapture) {
|
||||
listener(syntheticEvent);
|
||||
// event bubbles flag has higher priority
|
||||
if (!syntheticEvent.bubbles) {
|
||||
isStopBubble = true;
|
||||
}
|
||||
} else {
|
||||
isStopBubble = listener(syntheticEvent);
|
||||
// If callback have no return, use global bubble config to set isStopBubble.
|
||||
|
||||
Reference in New Issue
Block a user