简体   繁体   English

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

[英]Registering click on different components in React

I have a project underway with an interesting dilemma.我有一个正在进行的项目,有一个有趣的困境。 I have created a component (from Recommended way of making React component/div draggable ) and modified it so that the onMouseDown is only on the element not on document.我创建了一个组件(来自推荐的 React component/div draggable 方法)并对其进行了修改,以便 onMouseDown 仅在元素上而不在文档上。 In the same page I have an which is not registering the click event, although it receives focus on the right click.在同一页面中,我有一个没有注册点击事件,尽管它获得了右键单击的焦点。 I am enclosing my entire code here of both the element and the input layout if anybody can spot why I cannot click to focus on the text inputs.如果有人能发现为什么我不能单击以专注于文本输入,我将在此处附上元素和输入布局的整个代码。

Draggable.js 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;

And the function creating the draggable components: 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

Next the creation of the text boxes:接下来创建文本框:

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 >
        )

    }

and finally my render:最后是我的渲染:

   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>
            );
        }
    }

A lot of this code is still unrefined so if you see any changes that should be made please point them out also.很多此代码仍未完善,因此如果您看到任何应该进行的更改,请同时指出。 In the meantime, why do the text boxes in showStatus() not work?同时,为什么 showStatus() 中的文本框不起作用?

Thank you.谢谢你。

It turns out that the problem occurs when the form is in the ' component, which is applying onMouseDown to the container for the form.事实证明,当表单位于 ' 组件中时会出现问题,该组件将 onMouseDown 应用于表单的容器。 Once the was removed click events are registered correctly.一旦被删除点击事件被正确注册。

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

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