繁体   English   中英

在 React 中注册不同组件的点击

[英]Registering click on different components in React

我有一个正在进行的项目,有一个有趣的困境。 我创建了一个组件(来自推荐的 React component/div draggable 方法)并对其进行了修改,以便 onMouseDown 仅在元素上而不在文档上。 在同一页面中,我有一个没有注册点击事件,尽管它获得了右键单击的焦点。 如果有人能发现为什么我不能单击以专注于文本输入,我将在此处附上元素和输入布局的整个代码。

Draggable.js

import React from 'react';
import PropTypes from 'prop-types';

class Draggable extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            relX: 0,
            relY: 0,
            x: parseInt(props.left),
            y: parseInt(props.top),
            dragged: false
        };
        this.gridX = props.gridX || 2;
        this.gridY = props.gridY || 2;
        this.onMouseDown = this.onMouseDown.bind(this);
        this.onMouseMove = this.onMouseMove.bind(this);
        this.onMouseUp = this.onMouseUp.bind(this);
        this.onContext = this.onContext.bind(this);
        this.clickRef = React.createRef();
    }

    static propTypes = {
        onMove: PropTypes.func,
        onStop: PropTypes.func,
        onContext: PropTypes.func,
        left: PropTypes.number.isRequired,
        top: PropTypes.number.isRequired,
        gridX: PropTypes.number,
        gridY: PropTypes.number
    };

    onStart(e) {
        if (this.props.enabled) {
            this.setState({
                relX: e.pageX - this.props.left,
                relY: e.pageY - this.props.top
            })
        }
    }

    onMove(e, current) {
        if (this.props.enabled) {
            const x = Math.trunc((e.pageX - this.state.relX) / this.gridX) * this.gridX;
            const y = Math.trunc((e.pageY - this.state.relY) / this.gridY) * this.gridY;

            if (x !== this.state.x || y !== this.state.y) {
                this.setState({
                    x,
                    y,
                    dragged: true
                });
                this.props.onMove && this.props.onMove({ left: this.state.x, top: this.state.y });
            }
        }
    }

    onMouseDown(e) {
        if (e.button !== 0) return;
        this.onStart(e);
        this.clickRef.current.addEventListener('mousemove', this.onMouseMove);
        this.clickRef.current.addEventListener('mouseup', this.onMouseUp);
        e.preventDefault();
    }

    onMouseUp(e) {
        this.clickRef.current.removeEventListener('mousemove', this.onMouseMove);
        this.clickRef.current.removeEventListener('mouseup', this.onMouseUp);
        this.props.onStop && this.props.onStop(e, this.props.index ? this.props.index : null, { left: this.state.x, top: this.state.y, dragged: this.state.dragged });
        this.setState({ dragged: false });
        if (this.props.onStop) e.preventDefault();
    }

    onMouseMove(e) {
        this.onMove(e, this.props.index ? this.props.index : null, { left: this.state.x, top: this.state.y });
        e.preventDefault();
    }

    onContext(e) {
        if (this.props.onRightClick) {
            e.preventDefault();
            this.props.onRightClick(e, this.props.index ? this.props.index : null);
        }

    }

    render() {
        let style = {}
        if (this.props.style) {
            style = { ...this.props.style }
        }
        if (!(style.position && style.position === 'fixed')) {
            style.position = 'absolute';
        }
        style.left = this.state.x + 'px';
        style.top = this.state.y + 'px'

        return <div
            onMouseDown={this.onMouseDown}
            onContextMenu={this.onContext}
            onMouseMove={this.onMouseMove}
            onMouseUp={this.onMouseUp}
            style={style}
            ref={this.clickRef}
        >
            {this.props.children}
        </div>;
    }
}

export default Draggable;

function 创建可拖动组件:

    buildDesks = () => {
        const newScale = this.getScale();
        const layout = this.props.layout;
        let container = document.querySelector("#Layout_Map_Container");

        const desks = layout.desks;//.filter(desk => parseInt(desk.SiteId) === parseInt(map.id));
        let ret = desks.map((desk, index) => {
            let deskImg = null;
            try {
                let dImg = layout.deskTypes.find(d => parseInt(d.deskType) === parseInt(desk.deskType));
                deskImg = dImg.deskImage;
            }
            catch (ex) {
                console.log(ex);
            }
            const userName = desk.UserLogon !== (null || '') ? desk.UserLogon : "Unassigned";

            const top = Math.trunc(parseInt(parseInt(desk.y) * newScale));
            const left = Math.trunc(parseInt(parseInt(desk.x) * newScale));
           
            const imgStyle = {
                width: `${parseInt(parseInt(desk.width) * newScale)}px`,
                height: `${parseInt((parseInt(desk.height) * newScale))}px`,
                transform: `rotate(${parseInt(desk.rotation)}deg)`
            }
            const url = `data:image/jpeg;base64,${deskImg}`;
            try {
                return (
                    <Draggable key={desk.DeskID}
                        index={desk.DeskID}
                        enabled={this.state.edit}
                        left={left}
                        top={top}
                        onMove={this.updateProperties}
                        onStop={this.endMove}
                        onRightClick={this.rightClick}
                    >
                        <img style={imgStyle} alt={userName} src={url} />
                    </Draggable>
                );
            }
            catch (ex) {
                console.log(ex);
                return null;
            }
        });//desks.map
        return ret;
    }//buildDesks

接下来创建文本框:

showStatus = () => {
        //screen width - object width - right coordinate
        let left = parseInt(window.innerWidth - 225);
        let top = 106;

        // return (<div></div>);

        return (
            <Draggable enabled={true}
                top={top}
                left={left}
            >
                <div style={{ width: '200px' }} className='editData'
                    style={{ position: 'fixed', top: top + 'px', left: left + 'px' }}>
                    <Row className='statusRow'>
                        <Col sm={12}>
                            <div id="Layout_UserImg" title="Click to upload new user image">
                                <div id="Layout_UserImgLabel">
                                    Click to
                                    upload new
                                    user image</div>
                            </div>
                        </Col>
                    </Row>
                    <Row className='statusRow'>
                        <Col sm={5} className='statusDivHeading'>Manager</Col>
                        <Col sm={7} className='statusDivData'><input type='text' id="Layout_Manager" /></Col>
                    </Row>
                    <Row className='statusRow'>
                        <Col sm={5} className='statusDivHeading'>User</Col>
                        <Col sm={7} className='statusDivData'><input type='text' id="Layout_User" /></Col>
                    </Row>
                    <Row className='statusRow'>
                        <Col sm={5} className='statusDivHeading'>Emp. Id</Col>
                        <Col sm={7} className='statusDivData'><input type='text' id="Layout_EmpId" /></Col>
                    </Row>
                    <Row className='statusRow'>
                        <Col sm={5} className='statusDivHeading'>Extension</Col>
                        <Col sm={7} className='statusDivData'><input type='text' id="Layout_Extension" /></Col>
                    </Row>
                    <Row className='statusRow'>
                        <Col sm={5} className='statusDivHeading'>Department</Col>
                        <Col sm={7} className='statusDivData'><input type='text' id="Layout_Department" /></Col>
                    </Row>
                    <Row className='statusRow'>
                        <Col sm={5} className='statusDivHeading'>DB Id</Col>
                        <Col sm={7} className='statusDivData'><input type='text' id="Layout_DBRowId" /></Col>
                    </Row>
                    <Row className='statusRow'>
                        <Col sm={5} className='statusDivHeading'>Desk ID</Col>
                        <Col sm={7} className='statusDivData'><input type='text' id="Layout_DeskID" /></Col>
                    </Row>
                    <Row className='statusRow'>
                        <Col sm={5} className='statusDivHeading'>Assets</Col>
                        <Col sm={7} className='statusDivData'><input type='text' id="Layout_Assets" /></Col>
                    </Row>
                    <Row>
                        <Col>
                            <button onClick={this.updateStats}>Save Changes</button>
                        </Col>
                        <Col>
                            <button onClick={this.clearUserStats}>Clear all fields</button>
                        </Col>
                    </Row >
                </div >
            </Draggable >
        )

    }

最后是我的渲染:

   render() {
        if (this.props.layout.isLoading) {
            return (<Loading title="Site Layout" />);
        }
        else if (this.props.layout.isLoadingMap) {
            const map = this.props.layout.maps[this.props.layout.currentMap];
            const siteName = map.SiteName;
            return (
                <Row>
                    <Col sm={1}></Col>
                    <Col sm={10} id="Layout_Map_Container">
                        <Loading title={"map '" + siteName + "'"} />
                    </Col>
                </Row>
            );
        }
        else if (this.props.layout.mapLoaded) {
            return (
                <div>

                    <Row>
                        <Col sm={1}>
                            {this.showAdmin()}
                        </Col>
                        <Col sm={10}>
                            {this.state.details}
                        </Col>
                    </Row>
                    <Row>
                        <Col sm={1}>
                            <select onChange={(e) => this.changeMap(e.target)}>
                                {this.buildMapOptions()}
                            </select>
                        </Col>
                        <Col sm={10} id="Layout_Map_Container">
                            {this.buildMap()}
                            {this.buildDesks()}

                        </Col>
                    </Row >
                    {this.showStatus()}
                </div>
            );
        }
        else {
            return (
                <Row>
                    <Col sm={1}>
                        <select onChange={(e) => this.changeMap(e.target)}>
                            {this.buildMapOptions()}
                        </select>
                    </Col>
                    <Col sm={10} id="Layout_Map_Container">
                    </Col>
                </Row>
            );
        }
    }

很多此代码仍未完善,因此如果您看到任何应该进行的更改,请同时指出。 同时,为什么 showStatus() 中的文本框不起作用?

谢谢你。

事实证明,当表单位于 ' 组件中时会出现问题,该组件将 onMouseDown 应用于表单的容器。 一旦被删除点击事件被正确注册。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM