JS组件系列——自己动手封装bootstrap-treegrid组件
前言:最近产品需要设计一套相对完整的组织架构的解决方案,由于组织架构涉及到层级关系,在表格里面展示层级关系,自然就要用到所谓的treegrid。可惜的是,一些轻量级的表格组件本身并没有自带树形表格的功能,比如bootstrapTable就没有这个功能,怎么办呢?如果是jqgrid、easyUI的表格,treegrid的效果可以说是轻而易举就能解决,而项目目前用的就是bootstrapTable,不可能这个时候因为这个需求去换组件吧。博主分析了下,无非就两种解决方案:一种就是扩展bootstrapTable的treegrid功能;第二种就是再找一个单独的treegrid组件去实现这个功能。博主在网上找了下,找到了一个效果还不错的treegrid第三方组件,于是做了下封装,今天分享出来,供大家参考。
本文原创地址:http://www.cnblogs.com/landeanfen/p/6776152.html
一、开源的treegrid
1、组件效果预览
最原始的效果
bootstrap样式的效果
这个是组件最原始的效果,后面会告诉大家博主做了哪些封装以及加了哪些功能。
在此还是给出一个封装过的效果吧!
2、组件开源地址
最后还是给出github上面一个开源的treegrid组件。
github开源地址:https://github.com/maxazan/jquery-treegrid
文档示例地址:http://maxazan.github.io/jquery-treegrid/
bootstrap样式的demo以及使用:http://maxazan.github.io/jquery-treegrid/examples/example-bootstrap-3.html
二、封装treegrid
1、组件封装的必要性
(1)纵观组件的所有的demo和文档,基本都是说的我们直接写死的table标签,然后通过样式去确定父子关系,最后初始化得到效果,但大部分情况下,我们的表格数据都不是写死的,而是通过后台获取数据,然后将数据渲染到前端,最终得到我们想要的效果,如果根据组件目前的使用方式,我们得到一个集合数据之后,需要自己去拼接tr、td这些东西,这都是小事,最麻烦的是组件是有父子关系的,我们需要根据我们数据之间的关系转化为组件的父子关系,并且由于支持无限级,还涉及到数据的递归运算。这个复杂的过程是我们不想经常去做的,怎么办呢?最好的思路就是封装了,封装的时候麻烦一次,以后使用就简单了,可以说这是一件一劳永逸的事情。
(2)一般来说,既然是treegrid,肯定会有表头,而这个表头是根据数据来动态显示的。组件自带的效果可以自己写死表头,但还是那句话,使用的灵活性太差。
由于以上两点,于是才有了今天的这篇文章。
2、组件封装代码示例
首先我们将treegrid组件下载并引用到我们的项目里面,然后向其目录里面加一个extension的文件夹,里面添加一个jquery.treegrid.extension.js的文件。
然后就是最重要的jquery.treegrid.extension.js文件的内容:
(function ($) {
"use strict"; $.fn.treegridData = function (options, param) {
//如果是调用方法
if (typeof options == 'string') {
return $.fn.treegridData.methods[options](this, param);
} //如果是初始化组件
options = $.extend({}, $.fn.treegridData.defaults, options || {});
var target = $(this);
debugger;
//得到根节点
target.getRootNodes = function (data) {
var result = [];
$.each(data, function (index, item) {
if (!item[options.parentColumn]) {
result.push(item);
}
});
return result;
};
var j = 0;
//递归获取子节点并且设置子节点
target.getChildNodes = function (data, parentNode, parentIndex, tbody) {
$.each(data, function (i, item) {
if (item[options.parentColumn] == parentNode[options.id]) {
var tr = $('<tr></tr>');
var nowParentIndex = (parentIndex + (j++) + 1);
tr.addClass('treegrid-' + nowParentIndex);
tr.addClass('treegrid-parent-' + parentIndex);
$.each(options.columns, function (index, column) {
var td = $('<td></td>');
td.text(item[column.field]);
tr.append(td);
});
tbody.append(tr);
target.getChildNodes(data, item, nowParentIndex, tbody) }
});
};
target.addClass('table');
if (options.striped) {
target.addClass('table-striped');
}
if (options.bordered) {
target.addClass('table-bordered');
}
if (options.url) {
$.ajax({
type: options.type,
url: options.url,
data: options.ajaxParams,
dataType: "JSON",
success: function (data, textStatus, jqXHR) {
debugger;
//构造表头
var thr = $('<tr></tr>');
$.each(options.columns, function (i, item) {
var th = $('<th style="padding:10px;"></th>');
th.text(item.title);
thr.append(th);
});
var thead = $('<thead></thead>');
thead.append(thr);
target.append(thead); //构造表体
var tbody = $('<tbody></tbody>');
var rootNode = target.getRootNodes(data);
$.each(rootNode, function (i, item) {
var tr = $('<tr></tr>');
tr.addClass('treegrid-' + (j + i));
$.each(options.columns, function (index, column) {
var td = $('<td></td>');
td.text(item[column.field]);
tr.append(td);
});
tbody.append(tr);
target.getChildNodes(data, item, (j + i), tbody);
});
target.append(tbody);
target.treegrid({
expanderExpandedClass: options.expanderExpandedClass,
expanderCollapsedClass: options.expanderCollapsedClass
});
if (!options.expandAll) {
target.treegrid('collapseAll');
}
}
});
}
else {
//也可以通过defaults里面的data属性通过传递一个数据集合进来对组件进行初始化....有兴趣可以自己实现,思路和上述类似
}
return target;
}; $.fn.treegridData.methods = {
getAllNodes: function (target, data) {
return target.treegrid('getAllNodes');
},
//组件的其他方法也可以进行类似封装........
}; $.fn.treegridData.defaults = {
id: 'Id',
parentColumn: 'ParentId',
data: [], //构造table的数据集合
type: "GET", //请求数据的ajax类型
url: null, //请求数据的ajax的url
ajaxParams: {}, //请求数据的ajax的data属性
expandColumn: null,//在哪一列上面显示展开按钮
expandAll: true, //是否全部展开
striped: false, //是否各行渐变色
bordered: false, //是否显示边框
columns: [],
expanderExpandedClass: 'glyphicon glyphicon-chevron-down',//展开的按钮的图标
expanderCollapsedClass: 'glyphicon glyphicon-chevron-right'//缩起的按钮的图标 };
})(jQuery);
代码说明
1、为了避免和源组件的初始化冲突,我们自定义的组件取了一个别名,叫 treegridData 。我们使用组件的时候就通过treegridData来进行初始化,如果你觉得这个名称不顺眼,可以自行修改。
2、代码的封装思路基本是参考博主之前介绍组件的封装 http://www.cnblogs.com/landeanfen/p/5124542.html这一篇里面的内容来的。
3、defaults里面就是初始化组件的时候可以传递的参数,上述注释基本上写得比较清楚。id和parentId两个参数主要是用来描述数据之间的父子级关系,后面我们介绍组件时候的时候你一看就能明白。
4、博主加了几个自认为很有用的属性和方法,应该能减少一些使用的麻烦。比如初始化组件的时候是否展开所有的子节点、添加title、表格行的渐变色和表格边框等。
5、上述封装里面递归查找子节点的时候,每一次都需要遍历所有的数据去找子节点,效率偏低,如果你使用了类似linq to js之类的组件去操作js的集合,可以优化那部分代码,适当提高递归的效率。当然,如果你的结果集本身数据量不太大,这么写影响也不太大。
3、封装后的组件使用
我们在界面上面引用需要的css和js文件
<link href="~/Content/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<link href="~/Content/jquery-treegrid-master/css/jquery.treegrid.css" rel="stylesheet" /> <script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Content/bootstrap/js/bootstrap.min.js"></script>
<script src="~/Content/jquery-treegrid-master/js/jquery.treegrid.min.js"></script>
<script src="~/Content/jquery-treegrid-master/js/jquery.treegrid.bootstrap3.js"></script>
<script src="~/Content/jquery-treegrid-master/extension/jquery.treegrid.extension.js"></script>
然后定义一个空的table标签
<table id="tb" ></table>
最后就是js初始化了
$(document).ready(function () {
$('#tb').treegridData({
id: 'Id',
parentColumn: 'ParentId',
type: "GET", //请求数据的ajax类型
url: '/TestMVC/GetData', //请求数据的ajax的url
ajaxParams: {}, //请求数据的ajax的data属性
expandColumn: null,//在哪一列上面显示展开按钮
striped: true, //是否各行渐变色
bordered: true, //是否显示边框
//expandAll: false, //是否全部展开
columns: [
{
title: '机构名称',
field: 'Name'
},
{
title: '机构描述',
field: 'Desc'
}
]
});
});
当然啦,还得配上后台的取数据的方法
public class TestMVCController : Controller
{public JsonResult GetData()
{
var result = new List<object>();
result.Add(new { Id = , Name = "百度科技", Desc = "搜索巨头"});
result.Add(new { Id = , Name = "百度事业部", Desc = "搜索巨头",ParentId= });
result.Add(new { Id = , Name = "百度人事部", Desc = "搜索巨头", ParentId = });
result.Add(new { Id = , Name = "百度HH部", Desc = "搜索巨头", ParentId = });
result.Add(new { Id = , Name = "百度行政", Desc = "搜索巨头", ParentId = });
result.Add(new { Id = , Name = "百度YY部", Desc = "搜索巨头", ParentId = });
result.Add(new { Id = , Name = "百度BB部", Desc = "搜索巨头", ParentId = });
result.Add(new { Id = , Name = "搜狐科技", Desc = "IT" });
result.Add(new { Id = , Name = "搜狐信息部", Desc = "IT", ParentId = });
result.Add(new { Id = , Name = "搜狐人事", Desc = "IT", ParentId = });
result.Add(new { Id = , Name = "搜狐事业部", Desc = "IT", ParentId = });
result.Add(new { Id = , Name = "搜狐事业子部", Desc = "IT", ParentId = });
return Json(result, JsonRequestBehavior.AllowGet);
}
}
这里一看应该就能明白组件defaults里面的id和parentColumn的作用了吧。记得jqgrid里面使用treeview的时候用到了一个level用来判断是哪一级别的节点,博主觉得这样硬性要求返回数据里面加一个level属性有点不妥,所以我们约定如果当前记录的parentId为null或者空字符串的时候,这个节点就是根节点,然后根据根节点去递归找子节点。
使用后的各种效果示例如下。
初始化的时候配置expandAll: false得到的效果
增加隔行变色striped: true
增加表格边框bordered: true
综合效果
三、总结
至此本文就结束了,没有什么太高大上的技术,就是简单将一个第三方组件进行了一些封装,使得其使用起来更加方便而已。如果你项目中也正在为treegrid而纠结,何不试试呢。其实扩展bootstrapTable的treegrid功能的思路博主已经有了,等有时间在下篇给出说明。
如果你觉得本文能够帮助你,可以右边随意 打赏 博主,也可以 推荐 进行精神鼓励。你的支持是博主继续坚持的不懈动力。
本文原创出处:http://www.cnblogs.com/landeanfen/
欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利
JS组件系列——自己动手封装bootstrap-treegrid组件的更多相关文章
- JS组件系列——自己动手扩展BootstrapTable的treegrid功能
前言:上篇 JS组件系列——自己动手封装bootstrap-treegrid组件 博主自己动手封装了下treegrid的功能,但毕竟那个组件只是一个单独针对树形表格做的,适用性还比较有限.关注博主的 ...
- JS组件系列——分享自己封装的Bootstrap树形组件:jqTree
前言:之前的一篇介绍了下如何封装自己的组件,这篇再次来体验下自己封装组件的乐趣.看过博主博客的园友应该记得之前分享过一篇树形菜单的使用JS组件系列——Bootstrap 树控件使用经验分享,这篇里面第 ...
- JS组件系列——自己动手扩展BootstrapTable的 冻结列 功能:彻底解决高度问题
前言:一年前,博主分享过一篇关于bootstrapTable组件冻结列的解决方案 JS组件系列——Bootstrap Table 冻结列功能IE浏览器兼容性问题解决方案 ,通过该篇,确实可以实现bo ...
- JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐(二)
前言:上篇 JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐 分享了几个项目中比较常用的组件,引起了许多园友的关注.这篇还是继续,因为博主觉得还有几个非常简单.实用的组件,实在不愿自己 ...
- JS组件系列——基于Bootstrap Ace模板的菜单和Tab页效果分享(你值得拥有)
前言:最近园子里多了许多谈语言.谈环境.谈逼格(格局)的文章,看看笑笑过后,殊不知其实都是然并卵.提升自己的技术才是王道.之前博主分享过多篇bootstrap组件的文章,引起了很多园友的关注和支持,看 ...
- 【转】JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐(二)
前言:上篇 JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐 分享了几个项目中比较常用的组件,引起了许多园友的关注.这篇还是继续,因为博主觉得还有几个非常简单.实用的组件,实在不愿自己 ...
- JS组件系列——封装自己的JS组件,你也可以
前言:之前分享了那么多bootstrap组件的使用经验,这篇博主打算研究下JS组件的扩展和封装,我们来感受下JQuery为我们提供$.Extend的神奇,看看我们怎么自定义自己的组件,比如我们想扩展一 ...
- JS组件系列——表格组件神器:bootstrap table
前言:之前一直在忙着各种什么效果,殊不知最基础的Bootstrap Table用法都没有涉及,罪过,罪过.今天补起来吧.上午博主由零开始自己从头到尾使用了一遍Bootstrap Table ,遇到不少 ...
- JS组件系列——表格组件神器:bootstrap table(二:父子表和行列调序)
前言:上篇 JS组件系列——表格组件神器:bootstrap table 简单介绍了下Bootstrap Table的基础用法,没想到讨论还挺热烈的.有园友在评论中提到了父子表的用法,今天就结合Boo ...
随机推荐
- 用Jquery做一个时间日期选择器
今天我们就用Jquery做一个时间日期选择器,当打开网页时,文本框里面显示的是当前的日期,点击文本框可以出现年.月.日的下拉菜单,并且可以选择,会根据年份的选择判断是否是闰年,从而改变二月的天数,闰年 ...
- 学生选课数据库SQL语句45道练习题整理及mysql常用函数(20161019)
学生选课数据库SQL语句45道练习题: 一. 设有一数据库,包括四个表:学生表(Student).课程表(Course).成绩表(Score)以及教师信息表(Teacher).四 ...
- SignalR指定用户推送消息
一.首先,在MVC项目中安装SingalR包(SingalR2.0需要.net4.5以上,VS2010可以安装1.1.3版本,本例为VS2010+SignalR1.1.3). 打开工具-NuGet程序 ...
- web从入门开始(1)------简介
服务端与客户端 HTML简介
- JS 拖动DIV 需要JQUERY 支持
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 蓄水池抽样(原理&实现)
前言: 蓄水池抽样:从N个元素中随机的等概率的抽取k个元素,其中N无法确定. 适用场景: 模式识别等概率抽样,抽样查看渐增的log日志(无法先保存整个数据流然后再从中选取,而是期望有一种将数据流遍历一 ...
- Python可视化学习(1):Matplotlib的配置
Matplotlib是一个优秀的可视化库,它提供了丰富的接口,让Python的可视化落地显得非常容易上手.本系列是本人学习python可视化的学习笔记,主要用于监督自己的学习进度,同时也希望和相关的博 ...
- ie11强制兼容模式打开
<meta http-equiv="X-UA-Compatible" content="IE=edge">
- iOS最好用的引导页
最近项目结束的时候又要改引导页,之前写的启动页改起来太麻烦了,所以就直接封装一个,功能可能还不是很完善,但是感觉用起来也比较方便,在这里和大家分享一下. 这是github的下载地址:https://g ...
- as3中强制垃圾回收
private function doClearance():void { // trace("clear"); try{ new LocalConnection().connec ...