toc
Pragmatic-drag-and-drop是由 Atlassian 公司开发出来的一个前端组件库,把Pragmatic-drag-and-drop翻译为中文就是:“实用的拖放”,可以理解为Atlassian 在研发这个前端组件库的时候,是奔着实用主义去的,一般我们理解使用实用都会好想到:体积小,性能高,好用,使用,简单易用等关键字,没错,Pragmatic-drag-and-drop就是一个非常关注性能的拖放库。Pragmatic-drag-and-drop 一种低级拖放工具链,可广泛应用于现有的任何技术堆栈上进行任何拖放体验,包括react、svelte、vue、angular 等,不受特定技术栈的限制。
Pragmatic-drag-and-drop 支持开源协议,开源协议:GNU General Public License v2.0 ,用户可以自由根据自身的需求进行使用。Pragmatic-drag-and-drop 官网文档地址:https://atlassian.design/components/pragmatic-drag-and-drop/about,开源项目地址为:https://github.com/atlassian/pragmatic-drag-and-drop,开发语言为TypeScript,同学们可以登录网址学习Pragmatic-drag-and-drop是如何实现的。
使用场景分析:
Pragmatic-drag-and-drop本质就是一个小小的核心包,包含一系列可选包,它们可以轻松地与使用自己的技术堆栈进行交换。
Pragmatic-drag-and-drop已经完成了很多用户设计指南,其中体现了我们希望如何在产品中实现拖放,其中一些决策体现在一些可选包中。当然,也运行可以自由使用喜欢的任何设计语言。
Pragmatic-drag-and-drop包含一个核心包和许多可选包,为提供任何你想创建的拖放功能。Pragmatic-drag-and-drop具备如下几个特点:
4.7kB
大小,相比其他拖放框架,可谓是小巧可爱,功能强大啊。Pragmatic-drag-and-drop提供了可视化输出,以便我们能够超快地构建一致的用户体验。用户可以根据自己的实际情况创建楚自己的视觉样式。
为了用户带来出色的体验,Pragmatic-drag-and-drop同时提供了一个工具链,可以让我们快速友好的构建高性能的辅助技术流程,以实现任何体验。可选辅助控件基于 Atlassian 设计系统。如果不想使用 Atlassian Design System,可以根据用户指南,替换为我们自己的组件。
Pragmatic-drag-and-drop核心包包括任何拖放体验的所有基本构建块,核心包是 vanillaJS 库(用 TypeScript 编写),可以与任何视图库(例如react
、svelte
等vue
)一起使用。
安装pragmatic-drag-and-drop库:
# 安装包
yarn add @atlaskit/pragmatic-drag-and-drop
核心包包含适配器,监视器以及常用工具库等,下面分别一一介绍:
适配器包含元素适配器,文本选择适配器,外部适配器:
window
文件和文本)适配器至少需要提供以下两部分:
dropTargetForElements
)。monitorForExternal
)。引入监视器/放置目标,示例代码如下:
import {
dropTargetForExternal,
monitorForExternal,
} from '@atlaskit/pragmatic-drag-and-drop/external/adapter';
import {
dropTargetForElements,
monitorForElements,
} from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
import {
dropTargetForTextSelection,
monitorForTextSelection,
} from '@atlaskit/pragmatic-drag-and-drop/text-selection/adapter';
用于监听@atlaskit/pragmatic-drag-and-drop
拖动事件的方法,示例代码如下:
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
const cleanup = monitorForElements({
element: myElement,
onDragStart: () => console.log('an element started dragging'),
});
一些常见的小辅助函数,一般包含在主拖放包中,示例代码如下:
import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
const cleanup = combine(
draggable({
element: myElement,
}),
dropTarget({
element: myElement,
}),
);
下面我们将分别从性能,功能特性,社区,安装包大小,代码块大小,技术架构等卫队对react-beatiful-dnd
,react-dnd
,@dnd-kit
,pragmatic-drag-and-drap
这几个拖拽库进行对比分析。
Pragmatic-drag-and-drop针对性能进行了优化,下面根据drag-and-drop-performance-comparison 对react-beatiful-dnd
,react-dnd
,@dnd-kit
,pragmatic-drag-and-drap
分别在移动端,浏览器端,服务器段进行了比较,如下表所示:
组件 | 移动端交互时长 | 桌面端交互时长 | 服务端渲染时长 | 服务端渲染时长差 |
---|---|---|---|---|
Baseline (no drag and drop) |
| +0ms | 11.2ms | +0ms |
|
| +180ms | 22.1ms | +10.9ms |
|
| +166ms | 16.2ms | +5ms |
|
| +129ms | / | / |
Pragmatic drag and drop |
| +1ms | 11.3ms | +0.1ms |
通过更加直观的图标显示出来
可以看的出来,在移动端,Pragmatic-drag-and-drop比react-beatiful-dnd
快了进275ms,比react-dnd
更是快了287ms,用时6ms;在桌面端,Pragmatic-drag-and-drop比react-beatiful-dnd
快了进180ms,比react-dnd
是快了166ms,用时1ms;在服务端渲染时,Pragmatic-drag-and-drop比react-beatiful-dnd
快了进10ms,比react-dnd
是快了5ms,只用时0.1ms。Pragmatic-drag-and-drop在性能这方便是完全碾压其他几个库,真是实至名归的实用库啊。
上面我们分析了Pragmatic-drag-and-drop在性能方面的优势,是完全碾压其他几个库。那么在功能特性方面又有哪些优势呢?我们从包大小,延迟加载特性,可访问性,增量开发,兼容性,可控性以及文件,图片,画板等多个维度和其他几个库进行了对比分析,表格如下图所示:
上面详细的列出来Pragmatic-drag-and-drop在多个维度和其他库的对比,看的出来,Pragmatic-drag-and-drop不仅性能好,而且体积小,功能全面,真正算得上是一个全能手啊,尤其是在兼容性,图片处理,画板处理,增量开发和延迟加载等特性,真是亮瞎人双眼啊。
下面再附上一张Pragmatic-drag-and-drop与react-beatiful-dnd的简单对比图,方便同学们更加直观的对比俩者之间的功能,Pragmatic-drag-and-drop真的非常的NB。
上面我们对比了Pragmatic-drag-and-drop和其他几个库的性能和功能特性,下面我们再来看看他们的社区情况。目前看来,Pragmatic-drag-and-drop正在强劲的成长过程中,成长指数为77.2%,活跃度为7.4,成长的非常凶猛啊。虽然只有6864颗星,但是同学们完全不需要接下来的发展方向,赶快加入吧。Pragmatic-drag-and-drop的协议为GNU General Public License V2.0,所以我们完全不需要Pragmatic-drag-and-drop的使用版权等问题。Pragmatic-drag-and-drop正作为一颗耀眼的新星快速的升起来。
我们这里顺便对比一下Pragmatic-drag-and-drop的安装包大小及代码块大小,对比结论为:Pragmatic-drag-and-drop不仅代码库最小,比react-beatiful-dnd小了7.5倍,代码块也是最小的,比react-beatiful-dnd减少了26%,再次体现了它的实用性,非常方便前端开发同学们的使用,可谓是非常的友好。
组件 | 最小安装包 | 最小安装压缩包 | 99卡片代码块大小 |
---|---|---|---|
react-beatiful-dnd | 105Bk | 20Kb | 3.75Kb |
pragmatic-drag-and-drop | 11.9Kb | 4.3Kb(比react-beatiful-dnd小了7.5倍) | 2.62Kb(减少了26%) |
react-dnd | 33.9Kb | 9.1Kb | / |
@dnd-kit | 54.2Kb | 17/6Kb | / |
这里我们简单的对比一下react-beatiful-dnd和pragmatic-drag-and-drop的技术流程图,可以看的出来pragmatic-drag-and-drop通过极其简单的架构完成了拖拽功能设计的复杂技术流程,同学们需要实现拖拽功能是非常方便的。
这里再附上pragmatic-drag-and-drop的标准加载流程图:
pragmatic-drag-and-drop的延迟加载如下:
对pragmatic-drag-and-drop库的深入理解还请同学们自行学习,纸上得来终觉浅,绝知此事要躬行。
下面我们将根据官网的一个实例,学习使用 Pragmatic-drag-and-drop实现一些基本功能,包括可拖放、拖放目标和监视器,我们将创建一个带有可拖动棋子的棋盘,效果图如下:
我们第一步是允许棋子被拖动,Pragmatic-drag-and-drop提供了一个可拖动的函数draggable
,可以将其附加到元素以启用可拖动行为,为了使作品在拖动时淡入淡出,我们可以在可拖动的设置状态中使用 onDragStart 和 onDrop 参数,代码如下:
function Piece({ image, alt }: PieceProps) {
const ref = useRef(null);
const [dragging, setDragging] = useState<boolean>(false); // NEW
useEffect(() => {
const el = ref.current;
invariant(el);
return draggable({
element: el,
onDragStart: () => setDragging(true), // NEW
onDrop: () => setDragging(false), // NEW
});
}, []);
return (
<img
css={[dragging && hidePieceStyles, imageStyles]} // toggling css using state to hide the piece
src={image}
alt={alt}
ref={ref}
/>
);
}
有了可拖动的棋子,我们希望棋盘上的方块充当可以“放置”到的区域。为此,我们将使用dropTargetForElements
实用拖放功能,创建放置目标遵循与 相同的技术draggable
,代码如下:
function Square({ location, children }: SquareProps) {
const ref = useRef(null);
const [isDraggedOver, setIsDraggedOver] = useState(false);
useEffect(() => {
const el = ref.current;
invariant(el);
return dropTargetForElements({
element: el,
onDragEnter: () => setIsDraggedOver(true),
onDragLeave: () => setIsDraggedOver(false),
onDrop: () => setIsDraggedOver(false),
});
}, []);
const isDark = (location[0] + location[1]) % 2 === 1;
return (
<div
css={squareStyles}
style={{ backgroundColor: getColor(isDraggedOver, isDark) }}
ref={ref}
>
{children}
</div>
);
}
function getColor(isDraggedOver: boolean, isDark: boolean): string {
if (isDraggedOver) {
return 'skyblue';
}
return isDark ? 'lightgrey' : 'white';
}
最后实现棋子在掉落时移动方块,我们将使用monitorForElements
实用的拖放功能。监视器允许从代码库中的任何位置观察拖放交互。这使它们能够接收可拖放的目标数据并执行操作,而无需从组件传递状态,我们可以在棋盘的顶层放置一个监视器useEffect
,并监听棋子何时落入方格中,代码如下:
function Square({ pieces, location, children }: SquareProps) {
const ref = useRef(null);
const [state, setState] = useState<HoveredState>('idle');
useEffect(() => {
const el = ref.current;
invariant(el);
return dropTargetForElements({
element: el,
getData: () => ({ location }), // NEW
/*...*/
});
});
/*...*/
}
function Chessboard() {
const [pieces, setPieces] = useState<PieceRecord[]>([
{ type: 'king', location: [3, 2] },
{ type: 'pawn', location: [1, 6] },
]);
useEffect(() => {
return monitorForElements({
onDrop({ source, location }) {
const destination = location.current.dropTargets[0];
if (!destination) {
// if dropped outside of any drop targets
return;
}
const destinationLocation = destination.data.location;
const sourceLocation = source.data.location;
const pieceType = source.data.pieceType;
if (
// type guarding
!isCoord(destinationLocation) ||
!isCoord(sourceLocation) ||
!isPieceType(pieceType)
) {
return;
}
const piece = pieces.find(p =>
isEqualCoord(p.location, sourceLocation),
);
const restOfPieces = pieces.filter(p => p !== piece);
if (
canMove(sourceLocation, destinationLocation, pieceType, pieces) &&
piece !== undefined
) {
// moving the piece!
setPieces([
{ type: piece.type, location: destinationLocation },
...restOfPieces,
]);
}
},
});
}, [pieces]);
/*...*/
}
Pragmatic-drag-and-drop支持多种形态的拖拽场景,包括列表,面板,网格,表格,树,画板等,下面列出了一些案例,方便同学们参考学习。
本节我们学习了Pragmatic-drag-and-drop,一个高效的实用的前端拖放组件库,我们通过Pragmatic-drag-and-drop可以轻松的实现前端页面的拖放功能,而且不受前端技术框架的限制,真的是我们前端开发者的福音。Pragmatic-drag-and-drop以极其小的安装体积以及极快运行性能,广泛的应用技术支持快速的吸引了前端开发者的目光,如果你是一名前端开发者,正在考虑前端拖放场景的实现,Pragmatic-drag-and-drop真的是一个非常不错的选择,Pragmatic-drag-and-drop在不就的将来定会收到越来越多的关注,感兴趣的同学们赶快来学习吧。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。