前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【前端拖拽组件库】最强开源高性能组件库Pragmatic-drag-and-drop简介与分析

【前端拖拽组件库】最强开源高性能组件库Pragmatic-drag-and-drop简介与分析

原创
作者头像
Freedom123
发布2024-05-11 14:26:04
3020
发布2024-05-11 14:26:04
举报
文章被收录于专栏:DevOpsDevOps

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是如何实现的。

使用场景分析:

  • 1)Pragmatic-drag-and-drop是否适合引入到我的已有的前端系统中来?

Pragmatic-drag-and-drop本质就是一个小小的核心包,包含一系列可选包,它们可以轻松地与使用自己的技术堆栈进行交换。

  • 2)Pragmatic-drag-and-drop是否能够适配其他设计语言?

Pragmatic-drag-and-drop已经完成了很多用户设计指南,其中体现了我们希望如何在产品中实现拖放,其中一些决策体现在一些可选包中。当然,也运行可以自由使用喜欢的任何设计语言。

一、核心能力

1.低等级的拖放功能

Pragmatic-drag-and-drop包含一个核心包和许多可选包,为提供任何你想创建的拖放功能。Pragmatic-drag-and-drop具备如下几个特点:

  • Tiny:内核只有4.7kB 大小,相比其他拖放框架,可谓是小巧可爱,功能强大啊。
  • Incremental:增量导入,你只需要导入你需要的功能即可,不需要全部导入,对用户非常的友好。
  • Headless:完全渲染和样式控制,用户可以根据自己的使用场景完全定制化开发。
  • Framework agnostic:适用于任何前端框架,支持react、svelte、vue、angular 等。
  • Deferred compatible:延迟加载核心包和可选包,进一步提高页面加载速度,这点在后面会具体介绍,毕竟Pragmatic主打的就是性能。
  • Works everywhere:Pragmatic-drag-and-drop目前支持Firefox、Safari 和 Chrome、iOS 和 Android 等最常用的系统和浏览器。

2.可选可视化输出

Pragmatic-drag-and-drop提供了可视化输出,以便我们能够超快地构建一致的用户体验。用户可以根据自己的实际情况创建楚自己的视觉样式。

3.可选辅助控件

为了用户带来出色的体验,Pragmatic-drag-and-drop同时提供了一个工具链,可以让我们快速友好的构建高性能的辅助技术流程,以实现任何体验。可选辅助控件基于 Atlassian 设计系统。如果不想使用 Atlassian Design System,可以根据用户指南,替换为我们自己的组件。

二、核心包&其他包

Pragmatic-drag-and-drop核心包包括任何拖放体验的所有基本构建块,核心包是 vanillaJS 库(用 TypeScript 编写),可以与任何视图库(例如reactsveltevue)一起使用。

安装pragmatic-drag-and-drop库:

代码语言:shell
复制
# 安装包
yarn add @atlaskit/pragmatic-drag-and-drop

核心包包含适配器,监视器以及常用工具库等,下面分别一一介绍:

1.Adapter(适配器)

适配器包含元素适配器,文本选择适配器,外部适配器:

  • 元素适配器:处理可拖动元素的拖动
  • 文本选择适配器: 处理文本选择的拖动
  • 外部适配器:处理从当前窗口外部发起的拖动操作(例如来自其他或应用程序的window文件和文本)

适配器至少需要提供以下两部分:

  • 创建放置目标的方法(例如dropTargetForElements)。
  • 创建监视器的方法(例如monitorForExternal)。

引入监视器/放置目标,示例代码如下:

代码语言:shell
复制
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';

2.监视器

用于监听@atlaskit/pragmatic-drag-and-drop拖动事件的方法,示例代码如下:

代码语言:shell
复制
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';

const cleanup = monitorForElements({
  element: myElement,
  onDragStart: () => console.log('an element started dragging'),
});

3.常用工具库

一些常见的小辅助函数,一般包含在主拖放包中,示例代码如下:

代码语言:shell
复制
import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';

const cleanup = combine(
  draggable({
    element: myElement,
  }),
  dropTarget({
    element: myElement,
  }),
);

4.可选包

  • hitbox:在拖动目标时向放置目标添加其他信息
  • react-drop-indicator:渲染放下时的指标
  • flourish:使拖动操作更绚丽多彩的效果(例如,drop 时闪光)
  • auto-scroll:拖动操作期间更绚的自动滚动效果
  • react-accessibility:用于添加常见辅助功能控件的自定义组件
  • Live-Region:向屏幕阅读器用户发送消息的助手
  • react-beautiful-dnd-migration:支持从 react-beautiful-dnd 到 Pragmatic 拖放的快速迁移

三、性能/功能比较

下面我们将分别从性能,功能特性,社区,安装包大小,代码块大小,技术架构等卫队对react-beatiful-dnd,react-dnd,@dnd-kit,pragmatic-drag-and-drap这几个拖拽库进行对比分析。

1.性能比较

Pragmatic-drag-and-drop针对性能进行了优化,下面根据drag-and-drop-performance-comparisonreact-beatiful-dnd,react-dnd,@dnd-kit,pragmatic-drag-and-drap分别在移动端,浏览器端,服务器段进行了比较,如下表所示:

组件

移动端交互时长

桌面端交互时长

服务端渲染时长

服务端渲染时长差

Baseline (no drag and drop)

+0ms

+0ms

11.2ms

+0ms

react-beautiful-dnd

+275ms

+180ms

22.1ms

+10.9ms

react-dnd

+387ms

+166ms

16.2ms

+5ms

@dnd-kit

+131ms

+129ms

/

/

Pragmatic drag and drop

+6ms

+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在性能这方便是完全碾压其他几个库,真是实至名归的实用库啊。

2.功能特性比较

上面我们分析了Pragmatic-drag-and-drop在性能方面的优势,是完全碾压其他几个库。那么在功能特性方面又有哪些优势呢?我们从包大小,延迟加载特性,可访问性,增量开发,兼容性,可控性以及文件,图片,画板等多个维度和其他几个库进行了对比分析,表格如下图所示:

上面详细的列出来Pragmatic-drag-and-drop在多个维度和其他库的对比,看的出来,Pragmatic-drag-and-drop不仅性能好,而且体积小,功能全面,真正算得上是一个全能手啊,尤其是在兼容性,图片处理,画板处理,增量开发和延迟加载等特性,真是亮瞎人双眼啊。

下面再附上一张Pragmatic-drag-and-drop与react-beatiful-dnd的简单对比图,方便同学们更加直观的对比俩者之间的功能,Pragmatic-drag-and-drop真的非常的NB。

3.社区比较

上面我们对比了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正作为一颗耀眼的新星快速的升起来。

4.安装包及代码块比较

我们这里顺便对比一下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

/

5.技术架构比较

这里我们简单的对比一下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实现一些基本功能,包括可拖放、拖放目标和监视器,我们将创建一个带有可拖动棋子的棋盘,效果图如下:

1.构建可拖动棋子

我们第一步是允许棋子被拖动,Pragmatic-drag-and-drop提供了一个可拖动的函数draggable,可以将其附加到元素以启用可拖动行为,为了使作品在拖动时淡入淡出,我们可以在可拖动的设置状态中使用 onDragStart 和 onDrop 参数,代码如下:

代码语言:shell
复制
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}
    />
  );
}

2.构建放下效果

有了可拖动的棋子,我们希望棋盘上的方块充当可以“放置”到的区域。为此,我们将使用dropTargetForElements实用拖放功能,创建放置目标遵循与 相同的技术draggable,代码如下:

代码语言:shell
复制
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';
}

3.移动棋子

最后实现棋子在掉落时移动方块,我们将使用monitorForElements实用的拖放功能。监视器允许从代码库中的任何位置观察拖放交互。这使它们能够接收可拖放的目标数据并执行操作,而无需从组件传递状态,我们可以在棋盘的顶层放置一个监视器useEffect,并监听棋子何时落入方格中,代码如下:

代码语言:shell
复制
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 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 一、核心能力
    • 1.低等级的拖放功能
      • 2.可选可视化输出
        • 3.可选辅助控件
        • 二、核心包&其他包
          • 1.Adapter(适配器)
            • 2.监视器
              • 3.常用工具库
                • 4.可选包
                • 三、性能/功能比较
                  • 1.性能比较
                    • 2.功能特性比较
                      • 3.社区比较
                        • 4.安装包及代码块比较
                          • 5.技术架构比较
                          • 四、实操教程
                            • 1.构建可拖动棋子
                              • 2.构建放下效果
                                • 3.移动棋子
                                • 五、样例效果
                                • 小结
                                相关产品与服务
                                图片处理
                                图片处理(Image Processing,IP)是由腾讯云数据万象提供的丰富的图片处理服务,广泛应用于腾讯内部各产品。支持对腾讯云对象存储 COS 或第三方源的图片进行处理,提供基础处理能力(图片裁剪、转格式、缩放、打水印等)、图片瘦身能力(Guetzli 压缩、AVIF 转码压缩)、盲水印版权保护能力,同时支持先进的图像 AI 功能(图像增强、图像标签、图像评分、图像修复、商品抠图等),满足多种业务场景下的图片处理需求。
                                领券
                                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档