45fan.com - 路饭网

搜索: 您的位置主页 > 电脑频道 > 编程代码 > 阅读资讯:如何能够无限分级和增删改tree结构数据?

如何能够无限分级和增删改tree结构数据?

2016-08-16 06:21:23 来源:www.45fan.com 【

如何能够无限分级和增删改tree结构数据?

阅读目录

•无限分级
•jstree插件
•Demo
•创建Region实体
•满足jstree插件的数据对象Dto
•数据转换
•初始化获取转换后的数据
•前台数据加载
•其他操作
•通过按钮来操作增删改

无限分级

很多时候我们不确定等级关系的层级,这个时候就需要用到无限分级了。

说到无限分级,又要扯到递归调用了。(据说频繁递归是很耗性能的),在此我们需要先设计好表机构,用来存储无限分级的数据。当然,以下都是自己捣鼓的结果,非标准。谁有更好的设计望不吝啬赐教。

说来其实也简单,就是一个ID和父ID的关系。

如何能够无限分级和增删改tree结构数据?

以此类推,Id需要是唯一的,ParenId需要是Id列里面存在即可。这样我们就实现无限分级了,如果再加一列Sort排序就更完美了。

jstree插件

官方地址:https://www.jstree.com/

为什么要用这个插件?因为有方便的api给我们做数据绑定,且支持节点拖动来实现增删改,个人觉得这个功能挺强大的。

Demo

下面我们来基于jstree插件来实现无限分级数据操作。以区域数据操作为例,用Code First的方式来编写demo代码。

如何能够无限分级和增删改tree结构数据?

创建Region实体

为了配合插件自动生成的节点id,我们这里使用的Node和ParentNode来存储上下级关系(而不是上面说的id和parentid,但是实际效果是一样的)。

/// <summary>
/// 区域
/// </summary>
public class Region
{
 /// <summary>
 /// 主键id
 /// </summary>
 public int Id { get; set; }
 /// <summary>
 /// 名称
 /// </summary>
 public string Name { get; set; }
 /// <summary>
 /// 节点
 /// </summary>
 public string Node { get; set; }
 /// <summary>
 /// 父节点
 /// </summary>
 public string ParentNode { get; set; }
}

满足jstree插件的数据对象Dto

为了适应jstree插件的数据要求,我们需要把上面的数据转换成树状的数据对象。

/// <summary>
/// Dto
/// </summary>
public class RegionsTreeOutput
{
 /// <summary>
 /// Id
 /// </summary>
 public int RegionsId { get; set; }
 /// <summary>
 /// tree显示文本(对应region的name)
 /// </summary>
 public string text { get; set; }
 /// <summary>
 /// tree的id(对应Node)
 /// </summary>
 public string id { get; set; } 
 /// <summary>
 /// 子节点数据(此属性就体现的数据的层级关系)
 /// </summary>
 public List<RegionsTreeOutput> children { get; set; }
}

数据转换

 #region GetRegionTree 初始化数据获取 的辅助方法
 public RegionsTreeOutput LoadRegions(string id, List<Region> inRegions, RegionsTreeOutput outRegions)
 {
  List<Region> regions = inRegions.Where(t => t.ParentNode == id).ToList();
  if (outRegions == null)//加载父节点
  {
  outRegions = ToTreeData(regions[0]);
  LoadRegions(outRegions.id, inRegions, outRegions);
  }
  else//加载子节点
  {
  outRegions.children = ToTreesData(regions);
  if (regions.Count > 0)
  {
   for (int i = 0; i < regions.Count; i++)
   {
   LoadRegions(regions[i].Node, inRegions, outRegions.children[i]);//递归调用
   }
  }
  }
  return outRegions;
 }
 public RegionsTreeOutput ToTreeData(Region region)
 {
  var treeData = new RegionsTreeOutput();
  treeData.id = region.Node;
  treeData.text = region.Name;
  treeData.RegionsId = region.Id;  
  return treeData;
 }
 public List<RegionsTreeOutput> ToTreesData(List<Region> listRegion)
 {
  var regions = new List<RegionsTreeOutput>();
  for (int i = 0; i < listRegion.Count; i++)
  {
  regions.Add(ToTreeData(listRegion[i]));
  }
  return regions;
 }
 #endregion 

初始化获取转换后的数据

 /// <summary>
 /// 初始化数据获取
 /// </summary>
 /// <returns></returns>
 public JsonResult GetResultData()
 {
 TreeDbContext db = new TreeDbContext();
 var regions = db.Regions.Where(t => true).ToList();
 var regionObj = LoadRegions("-1", regions, null);
 return Json(regionObj);
 }

以上后台的数据差不多就完成了。

前台数据加载

 $(function () {
  $.post("/Home/GetResultData", null, function (sData) {
  treeObj = $('#jstree_demo').jstree({
   //, "checkbox"
   'plugins': ["contextmenu", "dnd", "search", "state", "types", "wholerow"],
   'core': {
   "animation": 0,
   "check_callback": true,
   'force_text': true,
   "themes": { "stripes": true },
   'data': sData
   },
   "types": {
   "default": {
    "icon": "fa fa-folder icon-state-warning icon-lg"
   },
   "file": {
    "icon": "fa fa-file icon-state-warning icon-lg"
   }
   },
   "contextmenu": {
   select_node: false,
   show_at_node: true,
   items: function (o, cb) {
    //因为这里我们之后需要定义多个项,所以通过对象的方式返回
    var actions = {};
    //添加一个"新增"右键菜单
    actions.create = {//这里的create其实阔以随意命名,关键是里面的 这里面的 action回调方法
    "separator_before": false,//Create这一项在分割线之前
    "separator_after": true,//Create这一项在分割线之后
    "_disabled": false, //false表示 create 这一项可以使用; true表示不能使用
    "label": "新增", //Create这一项的名称 可自定义
    "action": function (data) { //点击Create这一项触发该方法,这理还是蛮有用的
     var inst = $.jstree.reference(data.reference),
      obj = inst.get_node(data.reference);//获得当前节点,可以拿到当前节点所有属性
     //新加节点,以下三行代码注释掉就不会添加节点
     inst.create_node(obj, {}, "last", function (new_node) {
     setTimeout(function () { inst.edit(new_node); }, 0);//新加节点后触发 重命名方法,即 创建节点完成后可以立即重命名节点
     });
    }
    };
    if (o.id != "0001")//屏蔽对根节点的操作 “0001”改成根节点对应的真是id
    {
    //添加一个"重命名"右键菜单
    actions.rename = {
     "separator_before": false,
     "separator_after": false,
     "_disabled": false, //(this.check("rename_node", data.reference, this.get_parent(data.reference), "")),
     "label": "重命名",
     "action": function (data) {
     var inst = $.jstree.reference(data.reference),
      obj = inst.get_node(data.reference);
     inst.edit(obj);
     }
    }
    //添加一个"删除"右键菜单
    actions.delete = {
     "separator_before": false,
     "icon": false,
     "separator_after": false,
     "_disabled": false, //(this.check("delete_node", data.reference, this.get_parent(data.reference), "")),
     "label": "删除",
     "action": function (data) {
     var inst = $.jstree.reference(data.reference),
      obj = inst.get_node(data.reference);
     if (inst.is_selected(obj)) {
      inst.delete_node(inst.get_selected());
     }
     else {
      inst.delete_node(obj);
     }
     }
    };
    }
    return actions;//返回右键菜单项
   }
   },
  });
  });
 });

其他操作

//删除节点
$('#jstree_demo').on('delete_node.jstree', function (e, data) {  
  var id = data.node.original.RegionsId;  
  $.ajax({
  type: "get",
  url: "/Home/DeleteRegion?id=" + id,
  success: function (sData) {

  }
  }); 
 });
//移动节点
$('#jstree_demo').on('move_node.jstree', function (e, data) {
  saveRegions(data);
 });
//修改名
$('#jstree_demo').on('rename_node.jstree', function (e, data) {  
  saveRegions(data);
 });
//保存
function saveRegions(data) {  
  var id = data.node.original.RegionsId;
  var name = data.node.text;//修改后的name
  //var oldName = data.old;//原name  
  //var pNode = $('#jstree_demo').jstree().get_node(data.node.parent).original.RegionsId;
  var josnData = { "Id": id, "Node": data.node.id, "ParentNode": data.node.parent, "Name": name };
  $.ajax({
  url: "/Home/SaveRegions",
  data: josnData,
  success: function (sData) {   
   data.node.original.RegionsId = sData;
   data.node.state.opened = false;//是否展开
  }
  });
 }

当然,记得修改或是删除要取RegionsId这个对应后台实体的ID。

通过按钮来操作增删改

function createTree() { 
 var ref = $('#jstree_demo').jstree(true),
 sel = ref.get_selected();
 if (!sel.length) { return false; }
 sel = sel[0];
 sel = ref.create_node(sel, { "type": "file" });
 if (sel) {
 ref.edit(sel);
 }
};

function renameTree() {
 var ref = $('#jstree_demo').jstree(true),
 sel = ref.get_selected();
 if (!sel.length) { return false; }
 sel = sel[0];
 ref.edit(sel, function () {
 
 });
};

function deleteTree() {
 var ref = $('#jstree_demo').jstree(true),
 sel = ref.get_selected();
 if (!sel.length) { return false; }
 ref.delete_node(sel);
};

如果大家想了解详情请下载源码:

http://xiazai.jb51.net/201605/yuanma/TreeDemo(jb51.net).rar

关于无限分级和tree结构数据增删改的相关知识就给大家介绍到这里,希望对大家有所帮助!


本文地址:http://www.45fan.com/bcdm/63457.html
Tags: 数据 tree 结构
编辑:路饭网
推广内容
推荐阅读
热门推荐
推荐文章
关于我们 | 联系我们 | 友情链接 | 网站地图 | Sitemap | App | 返回顶部