【JS组件篇】使用拖拽组件 react-beautiful-dnd 实现工作台自定义布局功能

2023-11-12

项目要求

制作工作台页面:模块可根据后端配置动态展示,各模块可根据个人喜好进行拖拽布局,并保存。大致效果如下:

在这里插入图片描述

大致实现步骤

  • 整体布局。首先需要对设计稿进行分析,大致分为左右两部分,可根据后端配置动态展示左右两模块的展示内容,各模块相对独立,各自发送请求根据返回数据展示模块内数据。(此处样式布局方式不做赘述,但要注意考虑后期左右模块可通过拖拽方式更换位置,宽度可能变化,需注意各模块布局内容的自适应问题

  • 为页面布局添加 react-beautiful-dnd 拖拽组件。(组件的内部结构及参数API可查看文章末尾的参考文章)

实现代码

1.页面布局:
	<div className={styles.workbench}>
      <DragDropContext onDragEnd={onDragEnd}>
      	{/* 左侧中心布局 */}
        <Droppable droppableId="centerModule">
          {(provided) => (
            <div className={styles.centerLayout} ref={provided.innerRef} {...provided.droppableProps}>
              {renderDragItem(centerModuleList)}
              {provided.placeholder}
            </div>
          )}
        </Droppable>
      	{/* 右侧布局 */}
        <Droppable droppableId="rightModule">
          {(provided) => (
            <div className={styles.rightLayout} ref={provided.innerRef} {...provided.droppableProps}>
              {renderDragItem(rightModuleList)}
              {provided.placeholder}
            </div>
          )}
        </Droppable>
      </DragDropContext>
    </div>
2.拖拽结束的排序 js:
  // 中心模块数据
  const [centerModuleList, setCenterModuleList] = useState(Object.values(userWorkBenchConfig.centerModuleList));
  // 右侧模块数据
  const [rightModuleList, setRightModuleList] = useState(Object.values(userWorkBenchConfig.rightModuleList));

  // 深拷贝
  const deepClone = (orig) => {
    var copy = Object.create(Object.getPrototypeOf(orig))
    copyOwnPropertiesFrom(copy, orig);
    return copy;
  }
  const copyOwnPropertiesFrom = (target, source) => {
    Object.getOwnPropertyNames(source)
      .forEach(ele => {
        // 获取到每个属性的所有描述,然后重新定义对象的属性并返回此对象。
        var desc = Object.getOwnPropertyDescriptor(source, ele);
        Object.defineProperty(target, ele, desc)
      });
    return target;
  }  

  // 拖拽结束放置 - 若拖拽位置或布局有一定规则,可在此处进行判断校验,最后将排序好的布局存储起来
  const onDragEnd = (result) => {
  	// source 为源位置数据,destination 为目标位置数据
    const { destination, source } = result;
    const sourceIndex = source.index;
    const destinationIndex = destination.index;
    // 默认布局配置 - 默认中心布局为目标位置,右侧布局为源位置
    let targetModuleList = centerModuleList;
    let targetFn = setCenterModuleList;
    let sourceModuleList = rightModuleList;
    let sourceFn = setRightModuleList;
    // 若拖拽源和目标在同一Droppable中,则只需重新排序一个Droppable;
    // 若不在同一Droppable中,则两个模块都需重新排序
    if (destination.droppableId === source.droppableId) {
      if (sourceIndex === destinationIndex) {
        return;
      }
      if (destination.droppableId === 'rightModule') {
        targetModuleList = rightModuleList;
        targetFn = setRightModuleList;
      }
      const userList = deepClone(targetModuleList);
      const [draggedItem] = userList.splice(sourceIndex, 1);
      userList.splice(destinationIndex, 0, draggedItem);
      targetFn(userList);
    } else {
      if (destination.droppableId === 'rightModule') {
        targetModuleList = rightModuleList;
        targetFn = setRightModuleList;
        sourceModuleList = centerModuleList;
        sourceFn = setCenterModuleList;
      }
      // 深拷贝
      const targetList = deepClone(targetModuleList);
      const sourceList = deepClone(sourceModuleList);
      // 从源数据中取出放入目标数据中
      const [draggedSourceItem] = sourceList.splice(sourceIndex, 1);
      targetList.splice(destinationIndex, 0, draggedSourceItem);
      targetFn(targetList);
      sourceFn(sourceList);
    }
  };

在这里插入图片描述

参考文章:
组件标签结构参考:https://blog.csdn.net/dongliang3164/article/details/118905576
组件参数API参考:https://blog.csdn.net/tianxintiandisheng/article/details/107109890

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【JS组件篇】使用拖拽组件 react-beautiful-dnd 实现工作台自定义布局功能 的相关文章

  • Firebase,只得到新的孩子[重复]

    这个问题在这里已经有答案了 var firebase new Firebase firebaseRef on child added function snapshot 这将接收所有元素 有没有办法在创建新的 Firebase 引用时不接收
  • 位置特征检测:固定

    我正在尝试找到一个脚本来检测设备是否放置position fixed元素相对于视口而不是整个文档 目前 标准桌面浏览器和 Mobile Safari 适用于 iOS 5 都是这样做的 而 Android 设备则相对于整个文档放置固定元素 我
  • 如何正确清理来自 AngularJS 控制器的无效输入的表单?

    我有一个 AngularJS 表单 其中包含 除其他字段之外 类型之一url 后者很重要 因为这会强制相应的输入成为有效的 URL 在某些条件下 例如 要关闭具有此类表单的模式对话框 我想以编程方式清除该表单 为此 我实现了方法reset基
  • jQuery .push 到 .get 调用中的数组给出空结果

    谁能告诉我为什么下面给我一个空字符串 当我console log contentArray in the get 回调函数它显示数据 但是当我尝试在下面的代码中执行它时 结果为空 sectionArray contentArray func
  • 为什么 window 与 Internet Explorer 中的 window.self 不同?

    关于我如何遇到这个问题有一个复杂的背景故事 但为什么self属性不完全等于窗口本身 在 Safari 和 Firefox 及其朋友中 结果如我所料 gt window window self true gt window window se
  • 想要动态处理与分页相关的页码显示:ReactJS

    我有一些分页逻辑工作得很好 唯一的问题是我只能让它显示并固定数量的页面可供选择 现在我已经把它放到了 5 页 但我希望它能够根据总记录动态更改 假设我有 100 条记录 每页限制为 10 条 将有 10 页 现在我只能让它以这种方式显示 第
  • 从 React Native Js 代码调用 Android Native UI 组件方法

    我创建了一个 CustomView SignatureView java 它扩展了 LinearLayout 以捕获 Android Native 中的签名 并创建了SignatureCapturePackage java和Signatur
  • 在 React 应用程序的 shell 脚本中设置环境变量

    我正在尝试在 powershell 和 bash 脚本中设置一些环境变量 并在 ReactJS 应用程序中读取它们 shell脚本很简单 env AUTHDOMAIN some domain com env AUTHCLIENTID bun
  • 本地推送通知到在应用程序内运行 JS 代码的 Win8 Live Tile

    我正在尝试将更新发送到我的应用程序的磁贴 当应用程序运行时 这可以正常工作 例如 当用户单击按钮时 我可以轻松地将磁贴更新通知发送到磁贴 我无法解决的是当应用程序无法运行时如何更新磁贴 我找到的唯一选择是使用以下命令从远程 Web 服务器拉
  • 按下回车键时不刷新页面

    我遇到了一些问题 只要表单中有输入 回车键就会触发页面刷新 下面的代码 如果按下回车并且文本区域 input 中没有输入任何文本 则不会刷新页面 但是如果按下回车并且 input中有输入或者光标位于文本区域 我不确定是什么触发了它 因为 s
  • javascript 选择自定义光标 (svg)

    我正在动态地将光标更改为悬停时的本地 svg element on mouseover function this css cursor url svgs pointer svg 9 30 auto 工作正常 但我想选择该 svg 来操纵其
  • 如何使用角度材料在具有可扩展行的表格中创建嵌套垫表

    我有以下数据 id c9d5ab1a subdomain wing domain aircraft part id c9d5ab1a info mimetype application json info dependent parent
  • 如何使用 Javascript 设置查询字符串

    有没有办法使用 javascript 设置查询字符串的值 我的页面有一个过滤器列表 单击该列表时 它将更改右侧的页内结果窗格 我正在尝试更新 url 的查询字符串值 因此如果用户离开页面 然后单击 后退 按钮 他们将返回到最后一个过滤器选择
  • 如何从 Chrome React Dev Tools 打开 VS code 中的组件文件?

    是否可以右键单击 React Dev 工具下可见的组件 然后单击 在 IDE 中显示 从而在 VSCode 中打开该文件 这将是有益的 因为我不必去寻找该组件 我经常想在 VS Code 中查看某个组件的源代码 但由于组件的模块化复用 代码
  • 如何正确取消引用然后删除 JavaScript 对象?

    我想知道从内存中完全取消引用 JavaScript 对象的正确方法 确保删除时不会在内存中悬空 并且垃圾收集器会删除该对象 当我看这个问题时在 JavaScript 中删除对象 https stackoverflow com questio
  • 表单发布请求并存储收到的数据

    我有一个非常简单的表单 在提交时发出发布请求
  • 使用javascript动态更新css内容

    需要将 css 更新为动态值 我不确定最好的方法是什么 div style zoom 1 div 缩放级别将根据窗口大小调整触发 应用程序将相应缩放 我将此应用程序加载到 cordova 中并让它在 iPAD 中运行 然后我意识到需要使用
  • Rails 3.1+ 的 Jasmine 与 Mocha JavaScript 测试 [已关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我对茉莉花有经验并且非常喜欢它 有谁有 Jasmine 和 Mocha 的经验 特别是 Rails 的经验吗 我想知道是否值得转用 我已经在 J
  • 有没有办法使用 ko.observableArray 作为地图?

    有没有办法使用ko observableArray http knockoutjs com documentation observableArrays html像地图 字典一样 例如 var arr ko observableArray
  • 仅当显式选择行时才关闭 ui-bootstrap typeahead

    我创建了这个jsBin http jsbin com livuqafe 2 edit来证明我遇到的问题 如果您转到此处 请尝试输入 五 并继续 你的自然反应是输入 五 然后按 Tab 如果你想要 五百 你可以向下箭头一次 但是 在这种情况下

随机推荐