You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用JavaScript和jQuery实现Kendo TreeList带结构的复制粘贴?

实现Kendo TreeList多单元格结构化复制粘贴功能

完全可以通过JavaScript和jQuery实现该需求,以下是包含结构化复制到剪贴板和粘贴到TreeList指定位置的完整实现方案:

核心实现逻辑

1. 收集选中单元格的结构化数据

通过Kendo TreeList API获取选中单元格,按视觉行列顺序整理数据,同时关联对应列的字段信息,确保粘贴时能匹配数据字段。

2. 绑定复制快捷键(Ctrl+C)

监听键盘复制事件,将整理好的结构化数据转换为制表符分隔文本(兼容文本文件粘贴)和HTML表格格式(兼容富文本工具粘贴),写入系统剪贴板。

3. 绑定粘贴快捷键(Ctrl+V)

监听键盘粘贴事件,解析剪贴板数据,以当前选中的单元格为起始位置,批量更新TreeList数据源,支持自动填充现有行或新增行。

完整代码示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Kendo TreeList 复制粘贴示例</title>

    <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2023.1.117/styles/kendo.default-v2.min.css"/>

    <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
    <script src="https://kendo.cdn.telerik.com/2023.1.117/js/kendo.all.min.js"></script>
</head>
<body>
  
<div id="treeList"></div>
<script>
  // 初始化TreeList
  const treeList = $("#treeList").kendoTreeList({
    columns: [
      { field: "name", title: "姓名" },
      { field: "age", title: "年龄" }
    ],
    selectable: "multiple, cell",
    editable:"incell",
    dataSource: [
      { id: 1, parentId: null, name: "Jane Doe", age: 22 },
      { id: 2, parentId: 1, name: "John Doe", age: 24 },
      { id: 3, parentId: 1, name: "Jenny Doe", age: 3 },
      { id: 4, parentId: null, name: "Tom Smith", age: 30 },
      { id: 5, parentId: 4, name: "Amy Smith", age: 5 }
    ]
  }).data("kendoTreeList");

  // 收集选中单元格的结构化数据
  function getSelectedCellsData() {
    const selectedCells = treeList.select();
    if (selectedCells.length === 0) return null;

    // 按行分组,确保数据顺序正确
    const rows = {};
    selectedCells.each(function() {
      const cell = $(this);
      const row = cell.closest("tr");
      const rowIndex = row.index();
      const colIndex = cell.index();
      const field = treeList.columns[colIndex].field;
      const value = cell.text().trim();

      if (!rows[rowIndex]) rows[rowIndex] = [];
      rows[rowIndex].push({ field, value, colIndex });
    });

    // 转换为有序的行数据数组
    return Object.values(rows).map(rowCells => {
      // 按列索引排序,确保列顺序正确
      rowCells.sort((a, b) => a.colIndex - b.colIndex);
      return rowCells;
    });
  }

  // 绑定复制事件(Ctrl+C)
  $(document).on("keydown", function(e) {
    if ((e.ctrlKey || e.metaKey) && e.key === "c") {
      const selectedData = getSelectedCellsData();
      if (!selectedData) return;

      // 转换为制表符分隔文本(用于粘贴到文本文件)
      const textContent = selectedData.map(row => {
        return row.map(cell => cell.value).join("\t");
      }).join("\n");

      // 转换为HTML表格(用于富文本粘贴)
      const htmlContent = `<table><tbody>${selectedData.map(row => {
        return `<tr>${row.map(cell => `<td>${cell.value}</td>`).join("")}</tr>`;
      }).join("")}</tbody></table>`;

      // 写入剪贴板,同时支持文本和HTML格式
      navigator.clipboard.write([
        new ClipboardItem({
          "text/plain": new Blob([textContent], { type: "text/plain" }),
          "text/html": new Blob([htmlContent], { type: "text/html" })
        })
      ]);

      e.preventDefault();
    }
  });

  // 绑定粘贴事件(Ctrl+V)
  $(document).on("keydown", function(e) {
    if ((e.ctrlKey || e.metaKey) && e.key === "v") {
      const targetCells = treeList.select();
      if (targetCells.length === 0) return;

      // 获取粘贴起始位置的单元格
      const firstTargetCell = $(targetCells[0]);
      const targetRow = firstTargetCell.closest("tr");
      const targetRowUid = targetRow.data("uid");
      const targetColIndex = firstTargetCell.index();

      // 获取剪贴板数据
      navigator.clipboard.read().then(items => {
        for (const item of items) {
          if (item.types.includes("text/plain")) {
            item.getType("text/plain").then(blob => {
              blob.text().then(text => {
                // 解析制表符分隔的文本为二维数组
                const pastedData = text.split("\n").map(line => line.split("\t"));
                if (pastedData.length === 0) return;

                // 从起始位置开始批量更新数据
                const dataSource = treeList.dataSource;
                const targetItem = dataSource.getByUid(targetRowUid);
                if (!targetItem) return;

                // 获取目标行在数据源中的位置
                const targetIndex = dataSource.indexOf(targetItem);
                let currentRowIndex = targetIndex;

                pastedData.forEach((rowData, rowIdx) => {
                  // 确保数据源中有足够的行,超出则新增(可根据需求调整层级逻辑)
                  let currentItem = dataSource.at(currentRowIndex);
                  if (!currentItem) {
                    // 默认新增为根节点,可修改parentId调整层级
                    currentItem = { id: Date.now() + rowIdx, parentId: null };
                    dataSource.add(currentItem);
                  }

                  // 更新当前行的对应列数据
                  rowData.forEach((cellValue, colOffset) => {
                    const targetCol = treeList.columns[targetColIndex + colOffset];
                    if (targetCol && cellValue) {
                      currentItem[targetCol.field] = cellValue;
                    }
                  });

                  currentRowIndex++;
                });

                // 刷新TreeList
                dataSource.sync();
              });
            });
          }
        }
      });

      e.preventDefault();
    }
  });
</script>
</body>
</html>

功能说明

  • 复制功能:选中任意多单元格后按Ctrl+C,数据会以制表符分隔格式存入剪贴板,粘贴到记事本、Excel等工具时会自动保留表格结构。
  • 粘贴功能:选中目标起始单元格后按Ctrl+V,复制的数据会从该位置开始批量填充到TreeList中,超出现有行时会自动新增行(可修改代码调整新增行的层级逻辑)。
  • 兼容性:支持现代浏览器的Clipboard API,如需兼容旧版浏览器可替换为document.execCommand方案。

内容的提问来源于stack exchange,提问作者Sonic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 06:56:55