React-draggable npm 包可防止在输入字段内单击

Posted

技术标签:

【中文标题】React-draggable npm 包可防止在输入字段内单击【英文标题】:React-draggable npm package prevents clicking inside input field 【发布时间】:2018-08-21 22:26:33 【问题描述】:

我正在使用 npm 包“react-draggable”来允许拖动包含表单的元素。

现在我可以拖动我的元素,我很高兴...但是输入字段不可点击,因为您无法点击和输入。我唯一能做的就是单击并按住然后输入。

片段:

render() 
        return (
            <Draggable>
                <div className="pokedex">
                    <div className="screen">
                        this.state.isSearching ? (<Loader/>) : null
                        this.state.hasFound ? this.renderResult() : null
                        this.state.hasError ? (<p className="text-center error">this.state.hasError</p>) : null
                    </div>
                    <form onSubmit=(e) => this.onSubmit(e)>
                        <input className="field" type="text" placeholder="Who is this pokemon?" onChange=(e) => this.setPokemon(e.target.value)/>
                        this.state.isSearching ? <input className="button text-center" disabled type="submit" value="Find!"/> : <input className="button text-center" type="submit" value="Find!"/>
                    </form>
                    <div className="button-group">
                        <div className="blue-button"/>
                        <div className="green-button"/>
                        <div className="orange-button"/>
                    </div>
                </div>
            </Draggable>
        )
    

有没有办法避免这种行为?

【问题讨论】:

我会尝试将stopPropagation 添加到输入上的onMouseDownonMouseUp 事件 【参考方案1】:

在我这边,我必须编写一个小“观察者”来检测用户是否真的在拖动或点击。原理是计算拖动起点和拖动停止点的距离:

function useClickObserver(callback)

    const [dragStartPos, setDragStartPos] = React.useState(new Point())
    const onStart = (_, data) =>
    
        setDragStartPos(new Point(data.x, data.y))
    
    const onStop = (_, data) =>
    
        const dragStopPoint = new Point(data.x, data.y)
        if(Point.dist(dragStartPos, dragStopPoint) < 5)
        
            callback()
        
    
    return onStart, onStop

并将其注入 Draggable:

<Draggable
    onDrag=handleDrag
    ...useClickObserver(myOnClickCallback)
>

在此处查看完整源代码: https://gitlab.com/ggpack/banana/-/blob/master/src/components/Emitter.js#L22

实时示例 (PWA): https://ggpack.gitlab.io/banana

【讨论】:

【参考方案2】:

添加event.stopPropagation() onMouseDown 成功了!

防止当前事件在捕获和冒泡阶段进一步传播。

片段:

render() 
        return (
            <Draggable>
                <div className="pokedex">
                    <div className="screen">
                        this.state.isSearching ? (<Loader/>) : null
                        this.state.hasFound ? this.renderResult() : null
                        this.state.hasError ? (<p className="text-center error">this.state.hasError</p>) : null
                    </div>
                    <form onSubmit=(e) => this.onSubmit(e)>
                        <input onMouseDown=(e) => e.stopPropagation()  className="field" type="text" placeholder="Who is this pokemon?" onChange=(e) => this.setPokemon(e.target.value)/>
                        this.state.isSearching ? <input className="button text-center" disabled type="submit" value="Find!"/> : <input className="button text-center" type="submit" value="Find!"/>
                    </form>
                    <div className="button-group">
                        <div className="blue-button"/>
                        <div className="green-button"/>
                        <div className="orange-button"/>
                    </div>
                </div>
            </Draggable>
        )
    

【讨论】:

【参考方案3】:

stopPropagation() 不适合我。但是cancel 可以。

render() 
        return (
            <Draggable
             cancel=".field"
            >
                <div className="pokedex">
                    <div className="screen">
                        this.state.isSearching ? (<Loader/>) : null
                        this.state.hasFound ? this.renderResult() : null
                        this.state.hasError ? (<p className="text-center error">this.state.hasError</p>) : null
                    </div>
                    <form onSubmit=(e) => this.onSubmit(e)>
                        <input className="field" type="text" placeholder="Who is this pokemon?" onChange=(e) => this.setPokemon(e.target.value)/>
                        this.state.isSearching ? <input className="button text-center" disabled type="submit" value="Find!"/> : <input className="button text-center" type="submit" value="Find!"/>
                    </form>
                    <div className="button-group">
                        <div className="blue-button"/>
                        <div className="green-button"/>
                        <div className="orange-button"/>
                    </div>
                </div>
            </Draggable>
        )
    

【讨论】:

以上是关于React-draggable npm 包可防止在输入字段内单击的主要内容,如果未能解决你的问题,请参考以下文章

将 react-draggable 移动到屏幕的一侧?

使用react-draggable和react-resizable实现Ant Design Modal的拖动和拖拽改变宽度

使用react-draggable和react-resizable实现Ant Design Modal的拖动和拖拽改变宽度

哪个是为 Angular 应用程序执行谷歌分析的最佳 npm 包?

如何防止 NPM 自定义参数中的斜线扩展?

如何防止“npm install”或“npm remove”删除我的个人包?