下面直接给你最实用、最常见的树形菜单拖放控制(Draggable & Droppable Tree)方法,jQuery EasyUI 的 tree 组件内置支持拖拽节点(移动节点、排序、跨树拖拽),复制粘贴就能用,领导最爱的“菜单排序、部门调动、分类拖拽调整层级”效果全都有!
方法1:最简单最常用 – 开启基本拖放(推荐现在就用这个,3秒出效果)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>EasyUI 树形菜单 - 拖放控制</title>
<link rel="stylesheet" type="text/css" href="https://www.jeasyui.com/easyui/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="https://www.jeasyui.com/easyui/themes/icon.css">
<script type="text/javascript" src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script type="text/javascript" src="https://www.jeasyui.com/easyui/jquery.easyui.min.js"></script>
</head>
<body>
<div style="margin:30px;">
<div style="margin-bottom:15px;">
<a href="javascript:void(0)" class="easyui-linkbutton c6" iconCls="icon-save" onclick="saveTreeOrder()">保存排序</a>
<a href="javascript:void(0)" class="easyui-linkbutton" iconCls="icon-reload" onclick="$('#dragTree').tree('reload')">刷新</a>
</div>
<!-- 关键:dnd:true 开启拖放功能 -->
<ul id="dragTree" class="easyui-tree" data-options="
url:'get_menu_data.php', <!-- 可以静态标记或异步 -->
animate:true,
lines:true,
dnd:true <!-- 开启拖拽 -->
">
<!-- 静态示例(如果不用异步) -->
<li data-options="iconCls:'icon-setting'">
<span>系统管理</span>
<ul>
<li><span>用户管理</span></li>
<li><span>角色管理</span></li>
<li><span>部门管理</span></li>
<li><span>菜单管理</span></li>
</ul>
</li>
<li data-options="iconCls:'icon-product'"><span>商品管理</span></li>
<li data-options="iconCls:'icon-order'"><span>订单管理</span></li>
<li data-options="iconCls:'icon-report'"><span>报表统计</span></li>
</ul>
</div>
<script>
// 保存拖拽后的树结构(常用:获取所有节点顺序和层级)
function saveTreeOrder(){
var roots = $('#dragTree').tree('getRoots'); // 获取所有根节点
var treeData = [];
$.each(roots, function(i, root){
treeData.push(getNodeData(root));
});
console.log('拖拽后的树结构:', JSON.stringify(treeData, null, 2));
$.messager.alert('保存结果',
'<pre>' + JSON.stringify(treeData, null, 2) + '</pre>',
'info');
// 实际项目中:$.post('save_menu_order.php', {tree: treeData});
}
// 递归获取节点完整结构(id、text、children)
function getNodeData(node){
var data = {
id: node.id || null,
text: node.text,
iconCls: node.iconCls
};
var children = $('#dragTree').tree('getChildren', node.target);
if(children.length > 0){
data.children = [];
$.each(children, function(j, child){
data.children.push(getNodeData(child));
});
}
return data;
}
// 可选:拖拽事件监听
$('#dragTree').tree({
onDrop: function(target, source, point){
// point: 'append'(作为子节点)、'top'(插入到上方)、'bottom'(插入到下方)
console.log('节点 "' + source.text + '" 被拖放到 "' + $(target).parent().find('>span').text() + '" 的 ' + point);
},
onBeforeDrop: function(target, source, point){
// 可以在这里做限制,比如不允许某些节点拖拽
// return false; // 阻止拖放
return true;
}
});
</script>
</body>
</html>
效果亮点:
- 拖拽节点可移动到其他节点的上方、下方或作为子节点(三种放置方式)
- 拖拽时有清晰的插入线提示(top/bottom/append)
- 支持同级排序、跨层级移动(比如把“用户管理”拖到“商品管理”下面)
- 拖完后调用
saveTreeOrder()获取完整树结构,可直接保存到服务器
方法2:高级拖放控制(限制拖拽规则)
$('#dragTree').tree({
dnd: true,
onBeforeDrag: function(node){
// 禁止拖拽某些节点(比如根节点)
if(node.id == 1){
$.messager.alert('提示','根节点不允许拖拽!');
return false;
}
return true;
},
onBeforeDrop: function(target, source, point){
var targetNode = $('#dragTree').tree('getNode', target);
// 禁止把自己拖到自己子节点里(避免死循环)
if($('#dragTree').tree('isAncestor', source.target, target)){
return false;
}
// 只允许作为子节点(不允许同级排序)
if(point != 'append'){
return false;
}
// 只允许拖到有特定icon的节点下
if(targetNode.iconCls != 'icon-folder'){
return false;
}
return true;
}
});
方法3:行内拖拽排序(只允许同级排序,不允许跨层级)
onBeforeDrop: function(target, source, point){
var targetNode = $('#dragTree').tree('getNode', target);
var sourceParent = $('#dragTree').tree('getParent', source.target);
var targetParent = $('#dragTree').tree('getParent', target);
// 只允许同级拖拽(父节点相同)
if(sourceParent && targetParent && sourceParent.target === targetParent.target){
return point == 'top' || point == 'bottom'; // 只允许插入上下
}
return false;
}
方法4:两个树之间互相拖拽(跨树拖放)
<ul id="tree1" class="easyui-tree" data-options="dnd:true,url:'tree1.json'"></ul>
<ul id="tree2" class="easyui-tree" data-options="dnd:true,url:'tree2.json'"></ul>
<script>
$('#tree1').tree({
onDrop: function(target, source, point){
// source.tree 表示来源树(如果是跨树拖拽)
if(source.tree && source.tree[0] != this){
// 从tree2拖到tree1
$('#tree1').tree('append', {
parent: target,
data: [$.extend({}, source)] // 复制节点数据
});
$(source.tree).tree('remove', source.target); // 从原树删除
}
}
});
</script>
你现在直接复制方法1的完整代码运行,就能看到一个支持自由拖拽排序的树形菜单了!
拖拽完成后点击“保存排序”就能获取完整的树结构JSON,完美用于菜单排序、部门调整、分类管理等场景。
想要我给你一个完整的示例(异步树 + 拖拽排序 + 限制规则 + 保存到服务器 + 拖拽提示美化)?
或者你告诉我你的具体需求(比如“只允许同级排序”“不允许拖到叶子节点”“拖拽后自动展开”),我2分钟发你精准代码,复制就能跑!
快说说你想怎么控制拖放,我手把手帮你搞定,5分钟内看到超级专业的树形菜单拖拽效果!