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

如何在自定义jsTree上下文菜单中实现复制粘贴及文件/文件夹创建

jsTree 自定义上下文菜单实现(含创建分类、复制剪切粘贴)

以下是完整的实现代码,基于静态JSON数据构建jsTree,并实现你需要的所有上下文菜单功能:

<div id="jstree"></div>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" />

<script>
// 静态JSON数据
const treeData = [
  {
    id: "1",
    text: "根目录",
    type: "folder",
    children: [
      { id: "2", text: "文档文件夹", type: "folder", children: [{ id: "3", text: "简历.pdf", type: "file" }] },
      { id: "4", text: "图片文件夹", type: "folder", children: [{ id: "5", text: "头像.png", type: "file" }] }
    ]
  }
];

// 存储复制/剪切的节点信息
let clipboard = {
  node: null,
  action: null // 'copy' 或 'cut'
};

$(function() {
  $('#jstree').jstree({
    core: {
      data: treeData,
      check_callback: true // 允许修改树结构
    },
    types: {
      folder: {
        icon: "glyphicon glyphicon-folder-open"
      },
      file: {
        icon: "glyphicon glyphicon-file"
      }
    },
    contextmenu: {
      items: function(node) {
        const defaultItems = $.jstree.defaults.contextmenu.items();
        
        // 自定义创建菜单,拆分文件/文件夹选项
        defaultItems.create = {
          label: "创建",
          submenu: {
            create_folder: {
              label: "文件夹",
              action: function(data) {
                const inst = $.jstree.reference(data.reference);
                inst.create_node(node, { text: "新文件夹", type: "folder" }, "last", function(newNode) {
                  setTimeout(function() { inst.edit(newNode); }, 100);
                });
              }
            },
            create_file: {
              label: "文件",
              action: function(data) {
                const inst = $.jstree.reference(data.reference);
                inst.create_node(node, { text: "新文件.txt", type: "file" }, "last", function(newNode) {
                  setTimeout(function() { inst.edit(newNode); }, 100);
                });
              }
            }
          }
        };

        // 添加编辑子菜单(复制/剪切/粘贴)
        defaultItems.edit = {
          label: "编辑",
          submenu: {
            copy: {
              label: "复制",
              action: function(data) {
                const inst = $.jstree.reference(data.reference);
                clipboard.node = node;
                clipboard.action = 'copy';
              }
            },
            cut: {
              label: "剪切",
              action: function(data) {
                const inst = $.jstree.reference(data.reference);
                clipboard.node = node;
                clipboard.action = 'cut';
              }
            },
            paste: {
              label: "粘贴",
              action: function(data) {
                const inst = $.jstree.reference(data.reference);
                if (!clipboard.node || clipboard.node.id === node.id) return;
                
                // 仅允许粘贴到文件夹节点
                if (node.type !== 'folder') return;

                if (clipboard.action === 'copy') {
                  // 复制节点:深拷贝原节点数据,避免ID冲突
                  const copiedNode = JSON.parse(JSON.stringify(clipboard.node));
                  copiedNode.id = 'copy_' + Date.now(); // 生成新ID
                  inst.create_node(node, copiedNode, "last");
                } else if (clipboard.action === 'cut') {
                  // 剪切节点:移动后清空剪贴板
                  inst.move_node(clipboard.node, node, "last");
                  clipboard = { node: null, action: null };
                }
              },
              // 仅当剪贴板有内容且当前节点是文件夹时显示粘贴选项
              disabled: function() {
                return !clipboard.node || node.type !== 'folder';
              }
            }
          }
        };

        return defaultItems;
      }
    },
    plugins: ["contextmenu", "types"]
  });
});
</script>

关键功能解释

1. 创建菜单的文件/文件夹区分

通过在contextmenu.items中自定义create项,设置submenu拆分出"文件夹"和"文件"两个子选项,分别调用create_node时指定对应的type,同时创建后自动触发编辑状态(inst.edit(newNode)),方便用户直接修改名称。

2. 复制/剪切/粘贴实现

  • 剪贴板存储:用全局变量clipboard记录当前要操作的节点和操作类型(复制/剪切)。
  • 复制逻辑:深拷贝原节点数据并生成新ID(避免ID重复冲突),然后调用create_node添加到目标文件夹下。
  • 剪切逻辑:调用jsTree的move_node方法将原节点移动到目标位置,完成后清空剪贴板。
  • 粘贴权限控制:通过disabled属性控制粘贴按钮的可用性,仅当剪贴板有内容且目标节点是文件夹时才启用。

3. 基础功能(重命名/删除)

保留了jsTree默认上下文菜单中的重命名和删除功能,这些功能依赖check_callback: true配置,允许修改树结构。

内容的提问来源于stack exchange,提问作者Arup Ranjan Sahoo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 01:58:14