龙空技术网

React Dnd 的理解

小默科技 348

前言:

此刻同学们对“jqueryeasyuidnd”大体比较注重,兄弟们都需要分析一些“jqueryeasyuidnd”的相关文章。那么小编在网上汇集了一些有关“jqueryeasyuidnd””的相关文章,希望你们能喜欢,各位老铁们一起来了解一下吧!

React Dnd 是 redux 作者 Dan 另外一个非常赞的项目, dnd 是 Drag and Drop 的意思,为什么他会开发react-dnd 的项目,这个拖放库解决什么问题,和html 原生Drap Drop API 有什么样的联系和不同,设计是否有独特之处?让我们带着这些问题了解一下React Dnd吧.

React Dnd 是什么?

Reat Dnd 是React 和 Redux 的核心作者 Dan Abramov 创造的一组React 高阶组件,可以在保持组件分离的前提下帮助构建复杂的拖放接口。非常适合做类似jira 之类的应用程序,其中拖动在应用程序的不同部分之间传递数据,并且组件会根据拖放更改其外观和应用程序状态.

React Dnd 的出发点现有拖放插件的问题:jquery 插件思维模式,直接改变DOM拖放状态改变的影响不仅限于 CSS 类这种改变,不支持更加自定义Html5 拖放API 的问题不支持移动端拖动预览问题无法开箱即用React Dnd 的需求默认使用Html 拖放API.不支持操作dom.Dom 和拖放的源和目标解耦融入HTML5 拖放中获取类型匹配和数据传递的思想.React Dnd 的特点:

专注拖拽,不提供现成组件

React DnD提供了一组强大的API,但它不包含任何现成组件,而是采用包裹使用者的组件并注入 props 的方式。 它比jQuery UI等更底层,专注于使拖放交互正确,而把视觉方面的效果例如坐标限制交给使用者处理。这其实是一种关注点分离的原则,例如React DnD不打算提供可排序组件,但是使用者可以基于它快速开发任何需要的自定义的可排序组件。

单向数据流

类似于 React 一样采取声明式渲染,并且像 redux 一样采用单向数据流架构,实际上内部使用了 Redux.

隐藏了平台底层API的问题

HTML5拖放API充满了陷阱和浏览器的不一致。 React DnD为您内部处理它们,因此使用者可以专注于开发应用程序而不是解决浏览器问题。

可扩展可测试

React DnD默认提供了HTML5拖放API封装,但它也允许您提供自定义的“后端(backend)”。您可以根据触摸事件,鼠标事件或其他内容创建自定义DnD后端。例如,内置的模拟后端允许您测试Node环境中组件的拖放交互。

React Dnd 基本用法:

下面使用 React Dnd 做的一个TaskCard 的应用:

TaskCard 拖拽源代码如下:

import { Box, Badge, Text, Flex } from '@chakra-ui/core';import { ItemTypes } from '../utils/items';import { useDrag } from 'react-dnd';const TaskCard = props => {	const [{ isDragging }, drag] = useDrag({		item: {			type: ItemTypes.CARD,			id: props._id,		},		collect: monitor => ({			isDragging: !!monitor.isDragging(),		}),	});	return (		<Box			ref={drag}			my='4'			p={3}			bg='gray.500'			opacity={isDragging ? '0.5' : '1'}			boxShadow='sm'			w='100%'			rounded='md'			color='white'>			<Flex justify='space-between' my='2'>				<Text fontSize='lg' fontWeight='semibold'>					{props.title}				</Text>				<Badge					variantColor={props.category === 'Chores' ? 'green' : 'red'}					h='100%'>					{props.category}				</Badge>			</Flex>			<Text textAlign='center' fontSize='md'>				{props.details}			</Text>		</Box>	);};export default TaskCard;

react-dnd 封装了一个 useDrag 的hook ,暴露出 isDragging,drag 的属性。

放置目标的代码如下:

import { Box } from '@chakra-ui/core';import { useDrop } from 'react-dnd';import { ItemTypes } from '../utils/items';import { useContext } from 'react';import { CardContext } from '../pages/tasks';const BoxTarget = props => {	const { markAsDone } = useContext(CardContext);	const [{ isOver }, drop] = useDrop({		accept: ItemTypes.CARD,		drop: (item, monitor) => {			console.log('item',item);			return markAsDone(item.id);		},		collect: monitor => ({			isOver: !!monitor.isOver(),		}),	});	return (		<Box			ref={drop}			m={2}			p={3}			boxShadow='sm'			bg={isOver ? 'green.500' : 'green.200'}			minH='200px'			textAlign='center'			w='100%'			rounded='md'			color='white'>			{props.children}		</Box>	);};export default BoxTarget;

react-dnd 封装了一个 useDrop 的hook ,暴露出 drop 的属性。

源码地址:

React Dnd 整体架构图:

dnd-core

核心层主要用来实现拖放

实现了拖放管理器,定义了拖放的交互和框架无关,你可以基于它结合 react、jquery、RN等技术开发内部依赖了 redux 来管理状态实现了 DragDropManager,连接 BackendMonitor实现了 DragDropMonitor,从 store 获取状态,同时根据store的状态和自定义的状态获取函数来计算最终的状态实现了 HandlerRegistry 维护所有的 types定义了 Backend , DropTarget , DragSource 等接口工厂函数 createDragDropManager 用来接收传入的 backend 来创建一个管理器react-dnd

上层 React 版本的Drag and Drop的实现

提供 hooks、decorators API.通过业务层获取 backend 实现和组件来给核心层工厂函数通过核心层获取状态传递给业务层backend-html5主要暴露了一个工厂函数,传入 manager 来获取 HTML5Backend 实例HTML5Backend 实现了 Backend 接口

参考资料:

React DnD 拖放库浅析

The Future of Drag and Drop APIs

标签: #jqueryeasyuidnd