文档章节

利用 zTree 在 MVC 下实现树型结构管理

jamesvon
 jamesvon
发布于 2016/04/27 11:10
字数 2971
阅读 67
收藏 0

zTree 是一个依靠 jQuery 实现的多功能 “树插件”。优异的性能、灵活的配置、多种功能的组合是 zTree 最大优点。大家可以从 zTree 的官网下载和学习。

我这里通过自己的实践,简单介绍一下在.net MVC 环境下,如何实现 ztree 展示和管理树型结构的。

首先我们先假设一下任务,管理新闻的分类,先介绍一下数据结构。

我们还是先建立一个表结构对象和访问控制类

//新闻分类(VON_Catalog)
#region "新闻分类信息类声明"
namespace VonPortal.Web.Models
{
    /// <summary>新闻分类 信息类</summary>
    public class CatalogInfo
    {
        #region "Constructors"
        /// <summary>
        /// 构造函数
        /// </summary>
        public CatalogInfo()
        {
        }
        /// <summary>
        /// 含初始化构造函数
        /// </summary>
        /// <param name="ID">序号</param>
        /// <param name="CatalogName">分类名称</param>
        /// <param name="PID">父类序号</param>
        /// <param name="DisplayOrder">显示序号</param>
        /// <param name="Note">分类说明</param>
        public CatalogInfo(int ID, string CatalogName, int PID, int DisplayOrder, string Note)
        {
            this.ID = ID;
            this.CatalogName = CatalogName;
            this.PID = PID;
            this.DisplayOrder = DisplayOrder;
            this.Note = Note;
        }
        #endregion
        #region "Public Properties"
        /// <summary>序号</summary>
        [Required]
        [Display(Name = "序号")]
        public int ID { get; set; }
        /// <summary>分类名称</summary>
        [Display(Name = "分类名称")]
        public string CatalogName { get; set; }
        /// <summary>父类序号</summary>
        [Required]
        [Display(Name = "父类序号")]
        public int PID { get; set; }
        /// <summary>显示序号</summary>
        [Display(Name = "显示序号")]
        public int DisplayOrder { get; set; }
        /// <summary>分类说明</summary>
        [Display(Name = "分类说明")]
        public string Note { get; set; }
        #endregion
    }
}
#endregion
#region "新闻分类信息基础控制类声明"
namespace VonPortal.Web.Operators
{
    /// <summary>新闻分类 控制类</summary>
    public class CatalogCtrl
    {
        private CatalogDataProvider dataProvider = null;
        /// <summary>启动数据库事务</summary>
        public IDbTransaction BeginTrans()
        {
            dataProvider = CatalogDataProvider.CreateProvider();
            return dataProvider.DBBeginTrans();
        }
        /// <summary>含数据库事务的构造函数</summary>
        public CatalogCtrl(IDbTransaction DBTrans)
        {
            if (DBTrans == null)
                dataProvider = CatalogDataProvider.Instance();
            else
            {
                dataProvider = CatalogDataProvider.CreateProvider();
                dataProvider.DBTrans = DBTrans;
            }
        }
        //Read data and write to CatalogInfo class
        private void setInfoValue(IDataReader reader, CatalogInfo info)
        {
            info.ID = reader.GetInt32(0);  //序号
            info.CatalogName = reader.GetString(1);  //分类名称
            info.PID = reader.GetInt32(2);  //父类序号
            info.DisplayOrder = reader.GetInt32(3);  //显示序号
            info.Note = reader.GetString(4);  //分类说明
        }
        /// <summary>检验Catalog信息</summary>
        public string Check(CatalogInfo info)
        {
            string errInfo = "";
            return errInfo;
        }
        /// <summary>得到本节点的下属节点新的序号</summary>
        public int NewIdx(int PID)
        {
            return dataProvider.GetLasterOrder(PID) + 1;
        }
        /// <summary>
        /// 根据主键 PK_Catalog 提取信息
        /// </summary>
        /// <param name="ID">序号</param>
        public CatalogInfo GetByCatalog(int ID)
        {
            IDataReader reader = dataProvider.GetByCatalog(ID);
            if (!reader.Read())
            {
                reader.Close();
                return null;
            }
            CatalogInfo info = new CatalogInfo();
            setInfoValue(reader, info);
            reader.Close();
            return info;
        }
        /// <summary>得到所有信息</summary>
        public List<CatalogInfo> List()
        {
            List<CatalogInfo> list = new List<CatalogInfo>();
            IDataReader reader = dataProvider.List();
            while (reader.Read())
            {
                CatalogInfo info = new CatalogInfo();
                setInfoValue(reader, info);
                list.Add(info);
            }
            reader.Close();
            return list;
        }
        /// <summary>根据主键 IDX_Catalog 提取信息</summary>
        /// <param name="PID">父类序号</param>
        public List<CatalogInfo> ListByCatalog(int PID)
        {
            List<CatalogInfo> list = new List<CatalogInfo>();
            IDataReader reader = dataProvider.ListByCatalog(PID);
            while (reader.Read())
            {
                CatalogInfo info = new CatalogInfo();
                setInfoValue(reader, info);
                list.Add(info);
            }
            reader.Close();
            return list;
        }
        /// <summary>保存Catalog信息</summary>
        ///<param name="info">信息类</param>
        public bool Save(CatalogInfo info)
        {
            info.ID = dataProvider.Save(info.ID, info.CatalogName, info.PID, info.DisplayOrder, info.Note);
            return info.ID > 0;
        }
        /// <summary>添加Catalog信息</summary>
        ///<param name="info">信息类</param>
        public int Add(CatalogInfo info)
        {
            info.ID = dataProvider.Add(info.CatalogName, info.PID, info.DisplayOrder, info.Note);
            return info.ID;
        }
        /// <summary>修改Catalog信息</summary>
        ///<param name="info">信息类</param>
        public bool Edit(CatalogInfo info)
        {
            return dataProvider.Edit(info.ID, info.CatalogName, info.PID, info.DisplayOrder, info.Note) > 0;
        }
        /// <summary>根据PK_Catalog删除Catalog信息</summary>
        /// <param name="ID">序号</param>
        public int Del(int ID)
        {
            return dataProvider.Del(ID);
        }

    }
}
#endregion
#region "新闻分类信息操作控制类声明"
namespace VonPortal.Web.Tasks
{
    /// <summary>新闻分类 控制类</summary>
    public class CatalogTask : CatalogCtrl
    {
        /// <summary>含数据库事务的构造函数</summary>
        public CatalogTask(IDbTransaction DBTrans) : base(DBTrans)
        {
        }
        /// <summary>
        /// 根据主键 PK_Catalog 提取信息
        /// </summary>
        /// <param name="ID">序号</param>
        public new Task<CatalogInfo> GetByCatalog(int ID)
        {
            return Task.Run(() =>
            {
                return base.GetByCatalog(ID);
            });
        }
        /// <summary>根据主键 IDX_Catalog 提取信息</summary>
        /// <param name="PID">父类序号</param>
        public new Task<List<CatalogInfo>> ListByCatalog(int PID)
        {
            return Task.Run(() =>
            {
                return base.ListByCatalog(PID);
            });
        }
        /// <summary>保存Catalog信息</summary>
        ///<param name="info">信息类</param>
        public new Task<bool> Save(CatalogInfo info)
        {
            return Task.Run(() =>
            {
                return base.Save(info);
            });
        }
        /// <summary>添加Catalog信息</summary>
        ///<param name="info">信息类</param>
        public new Task<int> Add(CatalogInfo info)
        {
            return Task.Run(() =>
            {
                return base.Add(info);
            });
        }
        /// <summary>修改Catalog信息</summary>
        ///<param name="info">信息类</param>
        public new Task<bool> Edit(CatalogInfo info)
        {
            return Task.Run(() =>
            {
                return base.Edit(info);
            });
        }
        /// <summary>根据PK_Catalog删除Catalog信息</summary>
        /// <param name="ID">序号</param>
        public new Task<int> Del(int ID)
        {
            return Task.Run(() =>
            {
                return base.Del(ID);
            });
        }

    }
}
#endregion
#region "新闻分类信息数据库访问基类声明"
namespace VonPortal.Web.Data
{
    /// <summary>
    /// 数据及操作控制层
    /// <seealso cref="VonPortal.Web.Business.CatalogInfo"/>
    /// <seealso cref="VonPortal.Web.Business.CatalogCtrl"/>
    /// </summary>
    public abstract class CatalogDataProvider : DataProvider
    {
        #region Shared/Static Methods
        // singleton reference to the instantiated object 
        private static CatalogDataProvider objProvider = null;
        /// <summary>
        /// constructor
        /// </summary>
        static CatalogDataProvider()
        {
            objProvider = CreateProvider();
        }
        /// <summary>
        /// dynamically create provider
        /// </summary>
        /// <returns>return the provider</returns>
        public static CatalogDataProvider CreateProvider()
        {
            return (CatalogDataProvider)VonPortal.Web.Reflection.CreateDataProvider("von", "NewsModule", "VonPortal.Web.Data.CatalogDataProvider");
        }
        /// <summary>
        /// The instance of CatalogDataProvider.
        /// </summary>
        /// <returns>return the provider</returns>
        public static CatalogDataProvider Instance()
        {
            if (objProvider == null) objProvider = CreateProvider();
            return objProvider;
        }
        #endregion

        #region "Catalog Abstract Methods"
        /// <summary>根据主键 PK_Catalog 提取信息</summary>
        public abstract IDataReader GetByCatalog(int ID);
        /// <summary>得到本节点的最后节点序号</summary>
        public abstract int GetLasterOrder(int PID);
        /// <summary>根据主键 IDX_Catalog 提取信息</summary>
        public abstract IDataReader ListByCatalog(int PID);
        /// <summary>提取全部信息</summary>
        public abstract IDataReader List();
        /// <summary>保存Catalog信息</summary>
        public abstract int Save(int ID, string CatalogName, int PID, int DisplayOrder, string Note);
        /// <summary>添加Catalog信息</summary>
        public abstract int Add(string CatalogName, int PID, int DisplayOrder, string Note);
        /// <summary>修改Catalog信息</summary>
        public abstract int Edit(int ID, string CatalogName, int PID, int DisplayOrder, string Note);
        /// <summary>根据PK_Catalog删除Catalog信息</summary>
        public abstract int Del(int ID);
        #endregion
    }
}
#endregion

最后的VonPortal.Web.Data.CatalogDataProvider是数据库访问接口类,您可以根据自己的实际需求建立真实的数据库访问类,完成真正的数据库访问,我这里就不在详述了,下面将介绍今天的主角 zTree。大家可以通过 zTree 网上 API 来深入了解其代码编写规则,也可以下载 Demo 来进行研究。

首先按照常规我们先建立后台处理的Model和Controller。

using System.ComponentModel.DataAnnotations;
//新闻分类(VON_Catalog)
namespace VonPortal.Web.Modules
{
    public class CatalogModel
    {

        /// <summary>序号</summary>
        [Required]
        [Display(Name = "序号")]
        public int ID { get; set; }
        /// <summary>分类名称</summary>
        [Display(Name = "分类名称")]
        public string CatalogName { get; set; }
        /// <summary>父类序号</summary>
        [Required]
        [Display(Name = "父类序号")]
        public int PID { get; set; }
        /// <summary>显示序号</summary>
        [Display(Name = "显示序号")]
        public int DisplayOrder { get; set; }
        /// <summary>分类说明</summary>
        [Display(Name = "分类说明")]
        public string Note { get; set; }
    }
}

using System.Collections.Generic;
using System.Web.Mvc;
using VonPortal.Web.Models;
using VonPortal.Web.Operators;

namespace VonPortal.Web.Modules.Controllers
{
    public class NewsController : Controller
    {
        public ActionResult NewsCatalogManager()
        {
            return PartialView();
        }
        /// <summary>
        /// ajax 添加一个新闻分类
        /// </summary>
        /// <param name="PID">上级序号</param>
        /// <param name="CatalogName">分类名称</param>
        /// <param name="Note">分类说明</param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult NewCatalog(int PID, string CatalogName, string Note)
        {
            CatalogCtrl ctrl = new CatalogCtrl(null);
            CatalogInfo info = new CatalogInfo(0, CatalogName, PID, 0, Note);
            info.DisplayOrder = ctrl.NewIdx(PID);
            ctrl.Add(info);
            return Json(new { bRet = true, sMsg = "添加成功", html = info.ID.ToString() }, "text/html");
        }
        /// <summary>
        /// ajax 修改一个分类信息
        /// </summary>
        /// <param name="PID">上级序号</param>
        /// <param name="CatalogName">分类名称</param>
        /// <param name="Note">分类说明</param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult EditCatalog(int ID, string CatalogName, string Note)
        {
            CatalogCtrl ctrl = new CatalogCtrl(null);
            CatalogInfo info = ctrl.GetByCatalog(ID);
            info.CatalogName = CatalogName;
            info.Note = Note;
            ctrl.Edit(info);
            return Json(new { bRet = true, sMsg = "修改成功" }, "text/html");
        }
        /// <summary>
        /// ajax 删除一个新闻分类
        /// </summary>
        /// <param name="ID">分类序号</param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult DeleteCatalog(int ID)
        {
            CatalogCtrl ctrl = new CatalogCtrl(null);
            ctrl.Del(ID);
            return Json(new { bRet = true, sMsg = "删除成功" }, "text/html");
        }
        /// <summary>
        /// ajax 加载所有的新闻分类
        /// </summary>
        public void LoadCatalog()
        {
            List<CatalogInfo> lst = (new CatalogCtrl(null)).List();
            Response.Write("{[");
            foreach (CatalogInfo info in lst)
            {
                Response.Write("{ID:'" + info.ID.ToString() + "'");
                Response.Write(",CatalogName:'" + info.CatalogName + "'");
                Response.Write(",PID:'" + info.PID.ToString() + "'");
                Response.Write(",Note:'" + info.Note + "'},");
            }
            Response.Write("]}");
        }
    }
}

这里面我们建立的是一个 PartialView ,以便更好的加载到任何页面中。

我首先简要介绍一下 Controller 的内容;

public ActionResult NewsCatalogManager(); 完成页面的加载

public ActionResult NewCatalog(int PID, string CatalogName, string Note); 支持Ajax实现新分类的添加

public ActionResult EditCatalog(int ID, string CatalogName, string Note); 支持Ajax对现有分类信息的修改

public ActionResult DeleteCatalog(int ID); 支持Ajax删除一个分类节点

public void LoadCatalog();支持Ajax提取全部分类信息;

我们可以看到除了第一个 NewsCatalogManager()是系统加载使用的外,其余的全部采用Ajax的方式完成数据的管理;

下面我们看看也没事如何实现和完成信息调用的吧!

@model IEnumerable<VonPortal.Web.Models.CatalogInfo>
@{
    Layout = null;
}

@Html.Import("header", "zTreeStyle_css", @<link rel="stylesheet" href="/content/zTreeStyle.css" type="text / css">)
@Html.Import("header", "zTreeDemo_css", @<link rel="stylesheet" href="/content/Demo.css" type="text / css">)
@Html.Import("header", "ztree.1.js", @<script type="text/javascript" src="/scripts/jquery.ztree.core.js"></script>)
@Html.Import("header", "ztree.2.js", @<script type="text/javascript" src="/scripts/jquery.ztree.excheck.js"></script>)
@Html.Import("header", "ztree.3.js", @<script type="text/javascript" src="/scripts/jquery.ztree.exedit.js"></script>)

<style type="text/css">
    .ztree li span.button.add {
        margin-left: 2px;
        margin-right: -1px;
        background-position: -144px 0;
        vertical-align: top;
        *vertical-align: middle;
    }
</style>
<div class="content_wrap">
    <ul id="tree" class="ztree" style="width:260px; overflow:auto;"></ul>
</div>
<input id="catalogID" type="hidden" />
<div class="input-group">
    <span class="input-group-addon">分类名称</span><input id="catalogName" type="text" class="form-control" placeholder="分类名称" />
</div>
<textarea id="catalogNote" type="text" class="form-control" placeholder="分类说明" ></textarea>
<button type="button" class="btn btn-info" onclick="addNode($('#catalogName').val(), $('#catalogNote').val())">添加同级</button>
<button type="button" class="btn btn-info" onclick="addChild($('#catalogName').val(), $('#catalogNote').val())">添加下级</button>
<button type="button" class="btn btn-info" onclick="editNode($('#catalogName').val(), $('#catalogNote').val())">修改本级</button>

<script type="text/javascript">
    var setting = {
        view: { dblClickExpand: false, showLine: true, selectedMulti: false, selectedMulti: false },
        data: { key: { name: "CatalogName" }, simpleData: { enable: true, idKey: "ID", pIdKey: "PID", rootPId: 0 } },
        edit: {
            enable: true,
            editNameSelectAll: true,
            showRemoveBtn: function (treeId, treeNode) { return !treeNode.isParent; },
            removeTitle: "删除节点",
            showRenameBtn: true,
            renameTitle: "修改节点"
        },
        callback: {
            beforeRemove: function (treeId, treeNode) {
                var zTree = $.fn.zTree.getZTreeObj("tree");
                zTree.selectNode(treeNode);
                return confirm("确认删除 节点 -- " + treeNode.name + " 吗?");
            },
            onRemove: function (e, treeId, treeNode) {
                $.ajax({
                    type: 'POST', url: "News/DeleteCatalog", data: "ID=" + treeNode.ID, dataType: 'json', cache: false,
                    success: function (data) { return true; }
                });
            },
            beforeRename: function (e, treeId, treeNode, isCancel) {
                $.ajax({
                    type: 'POST', url: "News/EditCatalog", data: { "ID": treeId.ID, "CatalogName": treeNode, "Note": treeId.Note }, dataType: 'json', cache: false,
                    success: function (data) { return true; }
                });
            },
            onClick: function (event, treeId, treeNode) {
                var zTree = $.fn.zTree.getZTreeObj("tree");
                zTree.selectNode(treeNode);
                $("#catalogID").val(treeNode.ID);
                $("#catalogName").val(treeNode.CatalogName);
                $("#catalogNote").val(treeNode.Note);
            },
            onDrap:function (event, treeId, treeNodes, targetNode, moveType) {
                alert(treeNodes.length + "," + (targetNode ? (targetNode.tId + ", " + targetNode.name) : "isRoot" ));
            }
        }
    };
    $(function () {
        $.get("News/LoadCatalog", function (response) {
            var data = eval(response);
            $.fn.zTree.init($("#tree"), setting, data);
        });
    });
    function addNode(name, note)
    {
        var zTree = $.fn.zTree.getZTreeObj("tree");
        var nodes = zTree.getSelectedNodes();
        var pid = 0;
        if (nodes.length > 0) pid = nodes[0].PID;
        $.ajax({
            type: 'POST', url: "News/NewCatalog", data: { "PID": pid, "CatalogName": $("#catalogName").val(), "Note": $("#catalogNote").val() }, dataType: 'json', cache: false,
            success: function (data) {
                if (pid > 0) zTree.addNodes(nodes[0].getParentNode(), -1, { ID: data.html, CatalogName: $("#catalogName").val(), PID: pid, Note: $("#catalogNote").val() });
                else zTree.addNodes(null, -1, { ID: data.html, CatalogName: $("#catalogName").val(), PID: pid, Note: $("#catalogNote").val() });
            }
        });
    }
    function addChild(name, note) {
        var zTree = $.fn.zTree.getZTreeObj("tree");
        var nodes = zTree.getSelectedNodes();
        if (nodes.length < 1) alert("尚未选中节点");
        $.ajax({
            type: 'POST', url: "News/NewCatalog", data: { "PID": nodes[0].ID, "CatalogName": $("#catalogName").val(), "Note": $("#catalogNote").val() }, dataType: 'json', cache: false,
            success: function (data) {
                zTree.addNodes(nodes[0], -1, { ID: data.html, CatalogName: $("#catalogName").val(), PID: nodes[0].ID, Note: $("#catalogNote").val() });
            }
        });
    }
    function editNode(name, note) {
        var zTree = $.fn.zTree.getZTreeObj("tree");
        var nodes = zTree.getSelectedNodes();
        if (nodes.length < 1) alert("尚未选中节点");
        $.ajax({
            type: 'POST', url: "News/EditCatalog", data: { "ID": nodes[0].ID, "CatalogName": $("#catalogName").val(), "Note": $("#catalogNote").val() }, dataType: 'json', cache: false,
            success: function (data) {
                nodes[0].CatalogName = $("#catalogName").val();
                nodes[0].Note = $("#catalogNote").val();
                zTree.updateNode(nodes[0]);
            }
        });
    }
</script>

首先我们来分析一下 zTree 的配置信息,也就是setting

    var setting = {
        view: { dblClickExpand: false, showLine: true, selectedMulti: false, selectedMulti: false },
        data: { key: { name: "CatalogName" }, simpleData: { enable: true, idKey: "ID", pIdKey: "PID", rootPId: 0 } },
        edit: {
            enable: true,
            editNameSelectAll: true,
            showRemoveBtn: function (treeId, treeNode) { return !treeNode.isParent; },
            removeTitle: "删除节点",
            showRenameBtn: true,
            renameTitle: "修改节点"
        },
        callback: {
            beforeRemove: function (treeId, treeNode) {
                var zTree = $.fn.zTree.getZTreeObj("tree");
                zTree.selectNode(treeNode);
                return confirm("确认删除 节点 -- " + treeNode.name + " 吗?");
            },
            onRemove: function (e, treeId, treeNode) {
                $.ajax({
                    type: 'POST', url: "News/DeleteCatalog", data: "ID=" + treeNode.ID, dataType: 'json', cache: false,
                    success: function (data) { return true; }
                });
            },
            beforeRename: function (e, treeId, treeNode, isCancel) {
                $.ajax({
                    type: 'POST', url: "News/EditCatalog", data: { "ID": treeId.ID, "CatalogName": treeNode, "Note": treeId.Note }, dataType: 'json', cache: false,
                    success: function (data) { return true; }
                });
            },
            onClick: function (event, treeId, treeNode) {
                var zTree = $.fn.zTree.getZTreeObj("tree");
                zTree.selectNode(treeNode);
                $("#catalogID").val(treeNode.ID);
                $("#catalogName").val(treeNode.CatalogName);
                $("#catalogNote").val(treeNode.Note);
            },
            onDrap:function (event, treeId, treeNodes, targetNode, moveType) {
                alert(treeNodes.length + "," + (targetNode ? (targetNode.tId + ", " + targetNode.name) : "isRoot" ));
            }
        }
    };

重点是 Data 和 callback,在data里面我们指定了我们CatalogInfo的展示方式,也就是说zTree支持我们自定义数据的展示,我们在这里指定了,我们的展示数据和节点数据的内容:

data: { key: { name: "CatalogName" }, simpleData: { enable: true, idKey: "ID", pIdKey: "PID", rootPId: 0 } },

在callback中我们定义了所有zTree的操作交互内容:我们主要定义了以下几个相应事件:

通过这几个事件,我们就可以实现tree的修改和删除了。

最后为了完成分类信息的添加和全部信息的修改,我们建立了一个信息编辑区域:

<input id="catalogID" type="hidden" />
<div class="input-group">
    <span class="input-group-addon">分类名称</span><input id="catalogName" type="text" class="form-control" placeholder="分类名称" />
</div>
<textarea id="catalogNote" type="text" class="form-control" placeholder="分类说明" ></textarea>
<button type="button" class="btn btn-info" onclick="addNode($('#catalogName').val(), $('#catalogNote').val())">添加同级</button>
<button type="button" class="btn btn-info" onclick="addChild($('#catalogName').val(), $('#catalogNote').val())">添加下级</button>
<button type="button" class="btn btn-info" onclick="editNode($('#catalogName').val(), $('#catalogNote').val())">修改本级</button>

在这里面我们可以完成信息的同级添加和下级添加,同样,这是通过ajax完成的,对应的javascript函数是

这样我们就完成了zTree的主要基本操作和控制了。

看看我实现的界面效果:

呵呵,还可以吧!

© 著作权归作者所有

jamesvon
粉丝 3
博文 31
码字总数 47875
作品 0
河西
项目经理
私信 提问
ztree 能否实现像dtree那样 一个结点hover是一整条宽度吗?

@zTree 你好,想跟你请教个问题:ztree 能否实现像dtree那样 一个结点hover是一整条宽度吗? 最近要做个像windows资源管理器那样的左边树目录,发现ztree很强大,但看了下html结构,没法实现...

雾渺
2013/03/29
121
0
ztree 能否实现像dtree那样 一个结点hover时宽度是最大宽度吗?

@zTree 你好,想跟你请教个问题:ztree 能否实现像dtree那样 一个结点hover是一整条宽度吗? 最近要做个像windows资源管理器那样的左边树目录,发现ztree很强大,但看了下html结构,没法实现...

雾渺
2013/03/29
640
1
zTree 树 使用一个ul post 加载数据 其他 ul 数据直接从现成ul中提取数据并生成树有时会出现无法点击问题

zTree您好! 非常感谢您开发贡献的zTree插件程序,在同类型tree树插件中,zTree插件是用的最好最顺手的。 在使用过程中遇到一些问题,请您指教! 项目中使用了zTree功能,树节点数据由后台输...

yqqh
2012/12/11
1K
1
【开源访谈】zTree 作者张其纲访谈实录

关于开源访谈 开源访谈是开源中国推出的一系列针对国内优秀开源软件作者的访谈,以文字的方式记录并传播。我们希望开源访谈能全面的展现国内开源软件、开源软件作者的现状,着实推动国内开源...

虫虫
2012/07/31
12.2K
56
JQuery Tree插件——zTree v3.5.16 版发布

zTree v3.5.16 发布,继续缓慢的修正 bug google code 已经无法上传下载包,请使用 Github 或 开源中国的 Git。 GitHub:https://github.com/zTree/zTree_v3 开源中国Git:https://git.oschi...

zTree
2014/03/09
15.4K
13

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周一乱弹 —— 年迈渔夫遭黑帮袭抢

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @tom_tdhzz :#今日歌曲推荐# 分享Elvis Presley的单曲《White Christmas》: 《White Christmas》- Elvis Presley 手机党少年们想听歌,请使劲...

小小编辑
今天
1K
16
CentOS7.6中安装使用fcitx框架

内容目录 一、为什么要使用fcitx?二、安装fcitx框架三、安装搜狗输入法 一、为什么要使用fcitx? Gnome3桌面自带的输入法框架为ibus,而在使用ibus时会时不时出现卡顿无法输入的现象。 搜狗和...

技术训练营
昨天
5
0
《Designing.Data-Intensive.Applications》笔记 四

第九章 一致性与共识 分布式系统最重要的的抽象之一是共识(consensus):让所有的节点对某件事达成一致。 最终一致性(eventual consistency)只提供较弱的保证,需要探索更高的一致性保证(stro...

丰田破产标志
昨天
8
0
docker 使用mysql

1, 进入容器 比如 myslq1 里面进行操作 docker exec -it mysql1 /bin/bash 2. 退出 容器 交互: exit 3. mysql 启动在容器里面,并且 可以本地连接mysql docker run --name mysql1 --env MY...

之渊
昨天
12
0
python数据结构

1、字符串及其方法(案例来自Python-100-Days) def main(): str1 = 'hello, world!' # 通过len函数计算字符串的长度 print(len(str1)) # 13 # 获得字符串首字母大写的...

huijue
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部