Skip to content
This repository has been archived by the owner on Mar 7, 2024. It is now read-only.

Commit

Permalink
fix: 修复 onClick 和 onTouchStart 阻止冒泡会互相影响的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
Darmody committed Jul 9, 2020
1 parent 4c801d4 commit be9af42
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 42 deletions.
10 changes: 5 additions & 5 deletions packages/remax-runtime/src/SyntheticEvent/createCallbackProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ function isSyntheticType(inputType: string) {
return !!SYNTHETIC_TYPES.find(type => type === inputType);
}

function createBaseSyntheticEvent(node: VNode, nativeEvent: any) {
function createBaseSyntheticEvent(node: VNode, eventType: string, nativeEvent: any) {
if (!nativeEvent) {
return;
}

// 添加阻止冒泡方法
nativeEvent.stopPropagation = () => {
stopPropagation(node);
stopPropagation(node, eventType);
};

return nativeEvent;
Expand All @@ -31,10 +31,10 @@ export function createCallbackProxy(eventType: string, node: VNode, callback: (.
}

return function (nativeEvent: any, ...restParams: any) {
const syntheticEvent = createBaseSyntheticEvent(node, nativeEvent);
const syntheticEvent = createBaseSyntheticEvent(node, eventType, nativeEvent);

if (isPropagationStopped) {
validatePropagation(node);
if (isPropagationStopped[eventType]) {
validatePropagation(node, eventType);
return;
}

Expand Down
20 changes: 13 additions & 7 deletions packages/remax-runtime/src/SyntheticEvent/stopPropagation.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import VNode from '../VNode';
import { SYNTHETIC_TYPES } from './constants';

export let isPropagationStopped = false;
export const isPropagationStopped: {
[key: string]: boolean;
} = {};

SYNTHETIC_TYPES.forEach(type => {
isPropagationStopped[type] = false;
});

/**
* 检查父元素里还有没有点击事件
Expand All @@ -10,11 +16,11 @@ export let isPropagationStopped = false;
* @param {VNode} node
* @returns
*/
export function validate(node: VNode) {
export function validate(node: VNode, eventType: string) {
const parent = node.parent;

if (!parent) {
isPropagationStopped = false;
isPropagationStopped[eventType] = false;
return;
}

Expand All @@ -24,11 +30,11 @@ export function validate(node: VNode) {
}
}

validate(parent);
validate(parent, eventType);
}

export default function stopPropagation(node: VNode) {
isPropagationStopped = true;
export default function stopPropagation(node: VNode, eventType: string) {
isPropagationStopped[eventType] = true;

validate(node);
validate(node, eventType);
}
104 changes: 74 additions & 30 deletions packages/remax-runtime/src/__tests__/SyntheticEvent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,25 @@ import Container from '../Container';
class SyntheticEventTester {
callbacks: Array<((...params: any) => void) | null> = [];

constructor(callbacks: Array<((...params: any) => void) | null>) {
constructor(params: any[]) {
const container = new Container({});
const root = new VNode({
id: 1,
type: 'view',
container,
});

callbacks.reverse().reduce((parent, cb, index) => {
params.reverse().reduce((parent, [cb, event], index) => {
const node = new VNode({
id: index + 2,
type: 'view',
container,
props: {},
});

const callback = createCallbackProxy('onClick', node, cb || (() => void 0));
const callback = createCallbackProxy(event, node, cb || (() => void 0));
if (cb) {
node.props.onClick = callback;
node.props[event] = callback;
}

this.callbacks.unshift(cb ? callback : null);
Expand All @@ -40,7 +40,7 @@ class SyntheticEventTester {

describe('synthetic event', () => {
describe('stop propagation', () => {
it('only accept onClick', () => {
it('only accept valid type', () => {
const onTap = () => void 0;

const node = new VNode({
Expand All @@ -62,7 +62,11 @@ describe('synthetic event', () => {
const first = jest.fn();
const second = jest.fn();
const third = jest.fn();
const callbacks = [first, second, third];
const callbacks = [
[first, 'onClick'],
[second, 'onClick'],
[third, 'onClick'],
];
const tester = new SyntheticEventTester(callbacks);

tester.trigger();
Expand All @@ -86,17 +90,51 @@ describe('synthetic event', () => {
expect(() => newOnTap()).not.toThrow();
});

it('each type works independent', () => {
const first = jest.fn();
const second = jest.fn();
const third = jest.fn();
const callbacks = [
[
(e: any) => {
e.stopPropagation();
first();
},
'onClick',
],
[second, 'onTouchStart'],
[third, 'onClick'],
];

const tester = new SyntheticEventTester(callbacks);

tester.trigger();

expect(first).toBeCalled();
expect(second).toBeCalled();
expect(third).not.toBeCalled();

tester.trigger();

expect(first).toBeCalled();
expect(second).toBeCalled();
expect(third).not.toBeCalled();
});

it('stop at first', () => {
const first = jest.fn();
const second = jest.fn();
const third = jest.fn();
const callbacks = [
(e: any) => {
e.stopPropagation();
first();
},
second,
third,
[
(e: any) => {
e.stopPropagation();
first();
},
'onClick',
],
[second, 'onClick'],
[third, 'onClick'],
];

const tester = new SyntheticEventTester(callbacks);
Expand All @@ -119,15 +157,18 @@ describe('synthetic event', () => {
const second = jest.fn();
const third = jest.fn();
const callbacks = [
first,
null,
(e: any) => {
e.stopPropagation();
second();
},
null,
third,
null,
[first, 'onClick'],
[null, 'onClick'],
[
(e: any) => {
e.stopPropagation();
second();
},
'onClick',
],
[null, 'onClick'],
[third, 'onClick'],
[null, 'onClick'],
];

const tester = new SyntheticEventTester(callbacks);
Expand All @@ -150,15 +191,18 @@ describe('synthetic event', () => {
const second = jest.fn();
const third = jest.fn();
const callbacks = [
first,
null,
second,
null,
(e: any) => {
e.stopPropagation();
third();
},
null,
[first, 'onClick'],
[null, 'onClick'],
[second, 'onClick'],
[null, 'onClick'],
[
(e: any) => {
e.stopPropagation();
third();
},
'onClick',
],
[null, 'onClick'],
];

const tester = new SyntheticEventTester(callbacks);
Expand Down

0 comments on commit be9af42

Please sign in to comment.