在React应用程序中丢失touchmove事件

时间:2019-04-01 07:35:12

标签: reactjs typescript touch-event

我有一个很大的项目,例如用React用Typescript编写的网格

我有一些带有ontouchstart事件的div元素(是一个单元格)

render() {
    const matrix = this.props.cellMatrix;
    const disableUserSelectStyle: React.CSSProperties = {
        MozUserSelect: 'none',
        WebkitUserSelect: 'none',
        msUserSelect: 'none',
        userSelect: 'none'
    };
    // tslint:disable-next-line:jsx-wrap-multiline
    const content = (
        <div
            onKeyDown={e => this.handleKeyDown(e)}
            onKeyUp={e => this.handleKeyUp(e)}
            onCopy={e => this.handleCopy(e)}
            onCut={e => this.handleCut(e)}
            onPaste={e => this.handlePaste(e)}
            ref={ref => (this.gridElement = ref)}
            style={{
                ...this.props.style,
                ...disableUserSelectStyle,
                overflow: userIsMarkingGrid || columnIsMoving ? 'hidden' : 'auto'
            }}
            onScroll={_ => {
                this.handleScroll();
            }}
            data-cy="data-grid"
        >
            <div
                style={{ width: matrix.contentWidth, height: matrix.contentHeight, position: 'relative' }}
                onMouseDown={e => this.handleMouseDown(e)}
                onTouchStart={e => {
                    if (this.state.focusedLocation) {
                        this.handleTouchStart(e);
                    }
                }}
                onTouchEnd={e => this.handleTouchEnd(e)}
                onContextMenu={e => {
                    if (this.state.focusedLocation) {
                        this.handleContextMenu(e);
                        e.persist();
                    }
                }}
                onDoubleClick={e => this.handleDoubleClick(e)}
                onClick={e => this.handleClickCellOnlyForTouchDevices(e)}
                onMouseLeave={e => this.setState({ rowIdx: null })}
                ref={ref => (this.gridCellsContainerRef = ref)}
            >
                {matrix.frozenTopRange.height > 0 &&
                    this.renderRowPane(
                        { top: 0, position: 'sticky', zIndex: zIndex.horizontalPane },
                        matrix.frozenTopRange,
                        { bottom: true }
                    )}
                {matrix.scrollableRange.height > 0 &&
                    this.state.visibleRange &&
                    this.renderRowPane(
                        { height: matrix.scrollableRange.height },
                        matrix.scrollableRange.slice(this.state.visibleRange, 'rows'),
                        {}
                    )}
                {matrix.frozenBottomRange.height > 0 &&
                    this.renderRowPane(
                        { bottom: 0, position: 'sticky', zIndex: zIndex.horizontalPane },
                        matrix.frozenBottomRange,
                        { top: true, bottom: false }
                    )}
                {this.state.linePosition > 0 && this.renderLine()}
                {this.state.shadowPosition && this.renderShadow()}
                {this.state.currentBehavior.renderHiddenPart(
                    <div
                        className="hiddenElement"
                        contentEditable={true}
                        style={{ position: 'fixed', width: 1, height: 1, opacity: 0 }}
                        onBlur={e => {
                            if (this.state.isFocusedCellInEditMode) {
                                e.preventDefault();
                                e.stopPropagation();
                            }
                        }}
                        onPaste={e => e.preventDefault()}
                        ref={ref => (this.hiddenFocusElement = ref)}
                    />
                )}
            </div>
            {/* {this.renderCellContextMenu()} */}
        </div>
    );
    return content;
}
...
  1. 选择这些单元格后,在setState之后发生重新渲染,这改变了我的应用程序(选择单元格)的行为
  2. 此事件在类内部接收,该类不是组件(负责选择单元格的行为)
  3. 然后在窗口上添加了touchmove事件,该事件不会立即触发(这是一个问题)
export class CellSelectionBehavior extends DelegateBehavior {
    private clientX = 0; // for gridScrollHandler!
    private clientY = 0;
    private touch: boolean = false;

    private moveHandler = this.handleMove.bind(this);

    constructor(grid: Grid, event: any, private selectionType: 'cell' | 'row' | 'column', touch?: boolean) {
        super(
            new AutoScrollBehavior(
                new BasicGridBehavior(grid),
                selectionType === 'row' ? 'vertical' : selectionType === 'column' ? 'horizontal' : 'both'
            )
        );

        const positionX =
            event.type === 'mousedown' || event.type === 'click'
                ? event.clientX
                : event.type === 'touchstart'
                ? event.changedTouches[0].clientX
                : null;
        const positionY =
            event.type === 'mousedown' || event.type === 'click'
                ? event.clientY
                : event.type === 'touchstart'
                ? event.changedTouches[0].clientY
                : null;

        this.clientX = positionX;
        this.clientY = positionY;
        if (touch) {
            this.touch = touch;
            if (event.type === 'click') {
                this.setFocusLocation(grid, positionX, positionY);
                window.addEventListener('click', this.clickHandler);
            } else if (event.type === 'touchstart') {
                window.addEventListener('touchmove', this.moveHandler);
                window.addEventListener('touchend', this.touchEndHandler);
                this.grid.gridElement.addEventListener('scroll', this.gridScrollHandler);
            }
        } else {
            this.handleMouseDown(event);

            if (event.shiftKey && this.grid.state.focusedLocation) {
                this.updateCellSelection();
            }
            this.grid.gridElement.addEventListener('scroll', this.gridScrollHandler);
        }
    }
}
  1. 仅在第二次触摸后,事件才被触发...

我强调,pointer events可以正常运行,但是我不能使用它,因为它在Safari(iPad等)上不起作用

0 个答案:

没有答案