Skip to content

Commit 9f647c6

Browse files
authored
Merge pull request #2146 from didi/fix-event-mult-point
fix: 多指操作时只响应第一次的 tap & longpress 事件
2 parents 70c8e43 + 6958d44 commit 9f647c6

2 files changed

Lines changed: 48 additions & 24 deletions

File tree

packages/webpack-plugin/lib/runtime/components/react/getInnerListeners.ts

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ import {
1010
RemoveProps,
1111
InnerRef,
1212
LayoutRef,
13-
ExtendedNativeTouchEvent
13+
ExtendedNativeTouchEvent,
14+
GlobalEventState
1415
} from './types/getInnerListeners'
1516

16-
const globalEventState = {
17-
needPress: true
17+
const globalEventState: GlobalEventState = {
18+
needPress: true,
19+
identifier: null
1820
}
1921

2022
const getTouchEvent = (
@@ -137,39 +139,54 @@ function checkIsNeedPress (e: ExtendedNativeTouchEvent, type: 'bubble' | 'captur
137139
}
138140
}
139141

142+
function shouldHandleTapEvent (e: ExtendedNativeTouchEvent, eventConfig: EventConfig) {
143+
const { identifier } = e.nativeEvent.changedTouches[0]
144+
return eventConfig.tap && globalEventState.identifier === identifier
145+
}
146+
140147
function handleTouchstart (e: ExtendedNativeTouchEvent, type: EventType, eventConfig: EventConfig) {
141-
// 阻止事件被释放放回对象池,导致对象复用 _stoppedEventTypes 状态被保留
142148
e.persist()
143149
const { innerRef } = eventConfig
144-
globalEventState.needPress = true
145-
innerRef.current.mpxPressInfo.detail = {
146-
x: e.nativeEvent.changedTouches[0].pageX,
147-
y: e.nativeEvent.changedTouches[0].pageY
150+
const touch = e.nativeEvent.changedTouches[0]
151+
const { identifier } = touch
152+
153+
const isSingle = e.nativeEvent.touches.length <= 1
154+
155+
if (isSingle) {
156+
// 仅在 touchstart 记录第一个单指触摸点
157+
globalEventState.identifier = identifier
158+
globalEventState.needPress = true
159+
innerRef.current.mpxPressInfo.detail = {
160+
x: touch.pageX,
161+
y: touch.pageY
162+
}
148163
}
149164

150165
handleEmitEvent('touchstart', e, type, eventConfig)
151166

152167
if (eventConfig.longpress) {
153-
if (e._stoppedEventTypes?.has('longpress')) {
154-
return
155-
}
156-
if (eventConfig.longpress.hasCatch) {
157-
e._stoppedEventTypes = e._stoppedEventTypes || new Set()
158-
e._stoppedEventTypes.add('longpress')
168+
// 只有单指触摸时才启动长按定时器
169+
if (isSingle) {
170+
if (e._stoppedEventTypes?.has('longpress')) {
171+
return
172+
}
173+
if (eventConfig.longpress.hasCatch) {
174+
e._stoppedEventTypes = e._stoppedEventTypes || new Set()
175+
e._stoppedEventTypes.add('longpress')
176+
}
177+
innerRef.current.startTimer[type] && clearTimeout(innerRef.current.startTimer[type] as unknown as number)
178+
innerRef.current.startTimer[type] = setTimeout(() => {
179+
globalEventState.needPress = false
180+
handleEmitEvent('longpress', e, type, eventConfig)
181+
}, 350)
159182
}
160-
innerRef.current.startTimer[type] && clearTimeout(innerRef.current.startTimer[type] as unknown as number)
161-
innerRef.current.startTimer[type] = setTimeout(() => {
162-
// 只要触发过longpress, 全局就不再触发tap
163-
globalEventState.needPress = false
164-
handleEmitEvent('longpress', e, type, eventConfig)
165-
}, 350)
166183
}
167184
}
168185

169186
function handleTouchmove (e: ExtendedNativeTouchEvent, type: EventType, eventConfig: EventConfig) {
170187
const { innerRef } = eventConfig
171188
handleEmitEvent('touchmove', e, type, eventConfig)
172-
if (eventConfig.tap) {
189+
if (shouldHandleTapEvent(e, eventConfig)) {
173190
checkIsNeedPress(e, type, innerRef)
174191
}
175192
}
@@ -178,7 +195,9 @@ function handleTouchend (e: ExtendedNativeTouchEvent, type: EventType, eventConf
178195
const { innerRef, disableTap } = eventConfig
179196
handleEmitEvent('touchend', e, type, eventConfig)
180197
innerRef.current.startTimer[type] && clearTimeout(innerRef.current.startTimer[type] as unknown as number)
181-
if (eventConfig.tap) {
198+
199+
// 只有单指触摸结束时才触发 tap
200+
if (shouldHandleTapEvent(e, eventConfig)) {
182201
checkIsNeedPress(e, type, innerRef)
183202
if (!globalEventState.needPress || (type === 'bubble' && disableTap) || e._stoppedEventTypes?.has('tap')) {
184203
return

packages/webpack-plugin/lib/runtime/components/react/types/getInnerListeners.d.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,16 @@ interface ExtendedNativeTouchEvent extends NativeTouchEvent {
8484
_stoppedEventTypes?: Set<string>
8585
}
8686

87+
interface GlobalEventState {
88+
needPress: boolean
89+
identifier: null | number
90+
}
91+
8792
export {
8893
NativeTouchEvent,
8994
Props,
9095
AdditionalProps,
9196
RemoveProps,
92-
UseInnerPropsConfig,
9397
InnerRef,
9498
LayoutRef,
9599
PropsRef,
@@ -98,5 +102,6 @@ export {
98102
ExtendedNativeTouchEvent,
99103
EventConfig,
100104
RawConfig,
101-
EventType
105+
EventType,
106+
GlobalEventState
102107
}

0 commit comments

Comments
 (0)