- zTree v3.0 将核心代码按照功能进行了分割,不需要的代码可以不用加载
- 采用了 延迟加载 技术,上万节点轻松加载,即使在 IE6 下也能基本做到秒杀
- 兼容 IE、FireFox、Chrome、Opera、Safari 等浏览器
- 支持 JSON 数据
- 支持静态 和 Ajax 异步加载节点数据
- 支持任意更换皮肤 / 自定义图标(依靠css)
- 支持极其灵活的 checkbox 或 radio 选择功能
- 提供多种事件响应回调
- 灵活的编辑(增/删/改/查)功能,可随意拖拽节点,还可以多节点拖拽哟
- 在一个页面内可同时生成多个 Tree 实例
- 简单的参数配置实现 灵活多变的功能
强大的API文档,完全可以边学边做,一两天就可以设计出自己的树形菜单。笔者从初识到现在写这篇博文,也就学了3天的时间,所以有不到之处,请留言指正!
不费话了,直奔主题:《jQuery插件zTree前台拖拽排序自动保存到后台MySQL数据库的实现方法》
警告:笔者掉坑经验教训,请读者实验前,先备份好数据库,再来验证本文的可行性!
一、未雨绸缪——数据排序。要解决这个问题,需要先做好两件事:
1.数据库中要有Order字段(笔者的数据库字段为:ord),并构建zTree数据返回JSON,格式如下:
[
{
"id": 13,
"bid": 1010102,
"pId": 0,
"name": "人教版一年级数学上册",
"ord": 0,
"isParent": true
},
{
"id": 235,
"bid": 1010102,
"pId": 13,
"name": "1.准备课",
"ord": 1
},
{
"id": 236,
"bid": 1010102,
"pId": 235,
"name": "数一数",
"ord": 2
}
]
效果图:
其中:id、pId及name为zTree数据必备字段,bid和ord为自定义字段,ord为数据库输出及zTree显示的排序依据。
2.构建zTree数据时要根据Order字段进行排序。
排序方法很多,可自行百度,笔者采用的是前端排序(也可以数据库输出Json时排序):
$.getJSON(
"DemoJson.php",
{bid:bookID},
function(data){
var zNodes = data.sort(function(a,b){return a.ord - b.ord});//ord升序
var zTree = $.fn.zTree.init($("#zTree"), setting, zNodes);
}
);
DemoJson.php
<?php
header("content-type:application/json");// 尽量不要用text/json 某些浏览器会不兼容
$bid = intval($_GET['bid']);
$Json_Array=array();
if(!$bid){
$Sql = "Select cID as id,cBID as bid,cPID as pId,cName as name,cOrder as ord From `table` Where cName IS NOT NULL Order By ord Asc";
}else{
$Sql = "Select cID as id,cBID as bid,cPID as pId,cName as name,cOrder as ord From `table` Where cBID = ".$bid." Order By ord Asc";
}
$Data = $Conn -> query($Sql);
while($Rs = $Data->fetch_assoc()){
if($Rs["pId"] == 0){
$Rs["isParent"] = true;
}
$Json_Array[] = $Rs;
}
echo json_encode($Json_Array,JSON_NUMERIC_CHECK);//json形式返回
?>
然后我们一起来实现拖拽排序!!!
由于官方API缺乏对排序功能保存到后台的相关介绍,笔者搜索翻阅了很多资料,也没有找到有价值的信息,在一篇文章中,作者也只是大概说了一下,没有给出具体的Demo,所以看着前台完美的拖拽排序,一旦刷新又被打回原形,实属无奈!
二、珠联璧合——后台保存。经过仔细研究发现,要实现后台保存前台的排序,也只需要做两件事:
1.添加OnDrop回调函数
var setting = {
callback: {
onDrop: zTreeOnDrop
}
};
function zTreeOnDrop(event, treeId, treeNodes, targetNode, moveType) {
var zTree = $.fn.zTree.getZTreeObj(treeId);
var nodeData = zTree.transformToArray(zTree.getNodes());//获得前端zTree排序后的数据的数组
if(moveType){
SaveOrder(nodeData);//自定义函数:1.简化并构建排序数组,2.后台POST保存到数据库
}
};
function SaveOrder(data){
//data //排序后的zTree数组,节点太多,需要简化
var newData = [];//排序后的简化数组
$.each(data,function(i,item){
var a = {};
a["id"] = item.id;
a["pid"] = item.pId ? item.pId : 0;//根目录null转为0
a["bid"] = item.bid;
a["name"] = item.name;
a["ord"] = i;//核心:依据前端数组的位置遍序号
newData.push(a);
});
//更新数据库
$.post(
"DemoSave.php",
{json:JSON.stringify(newData)},
function(data){
if(data.ok){
console.log("okSaveOrder");
}else{
console.log("errSaveOrder");
}
},
"json"
);
}
2.后台数据库保存
由于是多条、多字段保存,所以需要批量更新数据库,笔者使用MySQL的replace into 语句:
DemoSave.php
<?php
header("content-type:application/json");// 尽量不要用text/json 某些浏览器会不兼容
$Json = $_POST["json"];//获取提交的Json数据
if($Json){
$arr = json_decode($Json, true);//解析Json为数组
$v = array();
foreach ($arr as $key => $val) {
$id = $val["id"];
$bid = $val["bid"];
$pid = $val["pid"];
$name = $val["name"];
$ord = $val["ord"];
$v[] = "($id,$bid,$pid,'$name',$ord)";
}
$value = join($v,",");//连接成Values字符串
//mysql 批量更新
//replace into test_tbl (id,dr) values (1,'2'),(2,'3'),...(x,'y');
$Sql = "replace into `table` (cID,cBID,cPID,cName,cOrder) values $value;";
$Data = $Conn -> query($Sql);
}
$Msg = array("ok"=>0);
if($Data){
$Msg["ok"] = 1;
}
echo json_encode($Msg,JSON_NUMERIC_CHECK);//json形式返回
?>
至此,前台拖拽后的任何变动信息都会完整的保存到数据库中,怎么刷新都不会改变了!
但需要注意的是:replace into操作本质是对重复的记录先delete后insert,如果更新的【字段不全】会将缺失的字段置为缺省值!!!
什么意思呢???
如果将DemoSave.php中的
$Sql = "replace into `table` (cID,cBID,cPID,cName,cOrder) values $value;";//数据库有5个字段
改为:
$Sql = "replace into `table` (cID,cPID,cOrder) values $value;";//只更新3个字段
则除了cID,cPID,cOrder外的所有字段cBID,cName都将会被设计数据库是的默认值填充。无形中将会丢失cBID,cName的数据!!!
再次警告:笔者掉坑经验教训,请读者实验前,先备份好数据库,再来验证本文的可行性!
后话:
1.笔者也想过只保存和记录被拖动的节点的位置信息,直接放弃了,为何?因为排列序号不完整!
2.批量更新的方式有很多种,replace into最容易构建SQL语句,所以笔者选了它,读者可以自行选择和构建保存SQL语句!
3.本例为PHP+MySQL保存排序的实例,对于其他后台语言,笔者尚未研究,也不会研究,因为不专业,所以别问我,希望专业人士自行扩展为其他后台语言保存排序的实例!
……
本文为原创作品,转载请注明出处!未经作者同意,不得发表于其他媒体!!