react-dnd 拖拽事件与输入框的文本选中冲突

问题描述

当我们使用拖拽库的时候,往往会遇到拖拽的一个元素他的子孙元素有输入框类型的dom节点,当拖拽的事件绑定在该元素身上时候,发现子孙的输入框不能进行文本选中了,会按住鼠标去选中文本的时候会触发拖拽

实际的效果,鼠标无法选中文本输入框中的值

解决1:拖拽事件绑定到子孙元素

不再将绑定事件绑到整个dom,使用拖拽句柄,在拖拽库中一般都有句柄的选项,可以把拖拽的事件绑定子孙的某个节点上,一般拖拽可以绑定 className='handle' 的节点去

每个库都有自己的写法,搜索一下即可

下面以react-draggable库为例子

js 复制代码
import Draggable from 'react-draggable';

function Component() {
  return (
    <Draggable handle=".handle">
      <div>
        <div className="handle"> Drag </div>
        <div> Content ...</div>
      </div>
    </Draggable>
  );
}

解决2:保持拖拽绑定,处理事件冲突

原理是在拖拽的事件中,判断当前触发拖拽事件的节点是否是 input框,如果是就阻止拖拽事件,自然就可以就行选择文本的操作了,

下面以reac-dnd库为例:

useDrag方法中canDrag方法中可以进行判断,返回一个false就可以阻止拖动,核心的判断是使用document.activeElement.tagName获取当前的激活事件的Dom节点的相关信息进行判断,相关的知识可以百度一下

js 复制代码
//下面只展示核心部分
import { DndProvider, useDrag, useDrop } from 'react-dnd';

const DragDom= () => {
  const [{ isDragging }, drag] = useDrag(() => ({
    type: 'aaa',
    canDrag: (m) => {
      if(document.activeElement.tagName === 'INPUT') return false
      return true
    },
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
    }),
  }));

  return (
    <div ref={drag}> Drag </div>
  );
};

最后大功告成

2024.12.23 更新

if(document.activeElement.tagName === 'INPUT') return false

这个判断改造了 改为下面的数组形式,需要什么类型的元素不被拖动就往数组里面加

js 复制代码
 	if(['INPUT', 'TEXTAREA'].some(i => i===document.activeElement.tagName)) return false

引申思考:

我们可以把不需要拖拽的元素写入某个特定的类名, 这不管元素如何布局都可以控制不拖动

下面是用于判断拖拽的伪代码

js 复制代码
<div>
	<div >元素1<div>
	<div class='不允许拖拽类名'>不可以动元素2<div>
	<div >元素3<div>
</div>

useDrag(() => ({
	canDrag: () => {
		if(document.activeElement的类名 === '不允许拖拽类名') return false
		return true
	}
}))
相关推荐
lichenyang4533 分钟前
从零开始写 HarmonyOS Web 容器:先让 ArkWeb 加载本地 H5
前端
kyriewen10 分钟前
一个看不见的撇号,让Claude Code追踪了中国开发者三个月
前端·ai编程·claude
莫生灬灬15 分钟前
DY联系人聊天Web面板支持获取联系人/聊天记录/发送消息
前端·chrome·websocket·c#
郑州光合科技余经理23 分钟前
海外外卖平台源码改造实战——多语言核心代码实现
java·开发语言·前端·后端·mysql·架构·php
一tiao咸鱼42 分钟前
前端转 agent # 02 - FastAPI 框架入门与原理
前端·python
wanghowie1 小时前
LangGraph4j 落地(二)— ReAct 多步工具与 trace 扩展
前端·react.js·前端框架
大家的林语冰1 小时前
Rust 再次打败 Go,Astro 7 首发,什么叫“万物皆可锈化“!
前端·javascript·性能优化
lichenyang4531 小时前
H5 如何调用 ArkTS:JavaScriptProxy、requestId 和 Promise 回调
前端
lichenyang4531 小时前
我在 HarmonyOS 上写了一个轻量级小程序运行时:从 Web 容器到 JSBridge
前端
雪隐1 小时前
用Flutter做背单词APP-02我画了设计稿,然后让AI帮我设计了数据库(顺便聊了会天)
前端·人工智能·后端