Bootstrap Tree View简单而优雅的树结构组件实例解析


Posted in Javascript onJune 15, 2017

A simple and elegant solution to displaying hierarchical tree structures (i.e. a Tree View) while leveraging the best that Twitter Bootstrap has to offer.

这是Bootstrap Tree View在git上的简介。

注意simple、elegant,简单而优雅,我喜欢这两个词。

那么今天的实例是通过Bootstrap Tree View来制作一款省市级菜单的应用。

一、效果图

Bootstrap Tree View简单而优雅的树结构组件实例解析 
Bootstrap Tree View简单而优雅的树结构组件实例解析 
Bootstrap Tree View简单而优雅的树结构组件实例解析 
Bootstrap Tree View简单而优雅的树结构组件实例解析

二、应用

①、首先,项目需要引入bootstrap.css、jquery.js、bootstrap-treeview.js

<link type="text/css" rel="stylesheet" href="${ctx}/components/bootstrap/css/bootstrap.min.css" rel="external nofollow" />
<script type="text/javascript" src="${ctx}/components/jquery/jquery-1.10.1.min.js"></script>
<script type="text/javascript" src="${ctx}/components/treeview/js/bootstrap-treeview.js"></script>

②、接下来,页面上需要放一个dom元素。

<div id="procitytree" style="height: 400px;overflow-y :scroll;"></div>

通过设置height和overflow-y,使treeview能够在垂直方向上出现滚动条。

③、由于省市级数据一般都是固定不变的,那么页面初次加载时,我们把省市级数据先拿到。

Java端非常简单:

@RequestMapping(value = "loadProcitysInfo")
public void loadProcitysInfo(HttpServletResponse response) {
 logger.debug("获取所有省市");
 try {
  List<Provincial> provincials = provincialService.getProvincials();
  for (Provincial provincial : provincials) {
   List<City> citys = cityService.getCitysByProvincialId(provincial.getId());
   provincial.setCitys(citys);
  }
  renderJsonDone(response, provincials);
 } catch (Exception e) {
  logger.error(e.getMessage(), e);
  logger.error(e.getMessage());
  renderJsonError(response, Constants.SERVER_ERROR);
 }
}

这段代码需要优化,通过mybatis其实可以一次就获得省级和市级的集合。

获取数据后,通过json写入到response中。

protected void renderJsonDone(HttpServletResponse response, final Object value) {
 Map<String, Object> map = new HashMap<String, Object>();
 map.put("statusCode", 200);
 map.put("result", value);
 String jsonText = JSON.toJSONString(map);
 PrintWriter writer = null;
 try {
  response.setHeader("Pragma", "no-cache");
  response.setHeader("Cache-Control", "no-cache");
  response.setDateHeader("Expires", 0);
  response.setContentType(contentType);
  writer = response.getWriter();
  writer.write(jsonText);
  writer.flush();
 } catch (IOException e) {
  throw new OrderException(e.getMessage());
 } finally {
  if (writer != null)
   writer.close();
 }
}

前端通过ajax对数据进行组装保存。

jQuery.ajax({
 url : common.ctx + "/procity/loadProcitysInfo", // 请求的URL
 dataType : 'json',
 async : false,
 timeout : 50000,
 cache : false,
 success : function(response) {
  var json = YUNM.jsonEval(response);

  if (json[YUNM.keys.statusCode] == YUNM.statusCode.ok) {
   var records = json[YUNM.keys.result];
   if (!json)
    return;
   // 城市列表都存在
   if (records != null && records.length > 0) {
    // 遍历子节点
    $.each(records, function(index, value) {
     var proNode = {};
     // text是显示的内容
     proNode["text"] = value.proname;
     proNode["id"] = value.id;
     proNode["procode"] = value.procode;
     // 节点不可选中
     proNode["selectable"] = false;
     // 初始化市级节点
     proNode["nodes"] = [];

     $.each(value.citys, function(index, value) {
      var cityNode = {};
      cityNode["text"] = value.cname;
      cityNode["id"] = value.id;
      cityNode["proid"] = value.proid;
      cityNode["code"] = value.code;
      // 节点不可选中
      cityNode["selectable"] = false;

      proNode["nodes"].push(cityNode);
     });
     // 保存页面端对象中
     //YUNM._set.procityTreeData的数据结构就是二维数组。
     YUNM._set.procityTreeData.push(proNode);
    });
   }
  }
 }
});

④、拿到数据之后,就可以对treeview进行初始化了。

这里,我们讲一点更复杂的应用,如下图。

Bootstrap Tree View简单而优雅的树结构组件实例解析

如果用户已经保存过一部分节点,那么初次展示的时候就需要通过treeview展示出来了。
我们定一些规则:

节点全部选中时color为red,check框选中。

节点未全部选中时color为red,check框未选中。

节点一个也没选中时color为默认,check框未选中。

为此,我们需要增加一点css。

/* 树形省市 */
.treeview .list-group-item.node-checked {
 color: red;
}
.treeview .list-group-item.node-selected {
 color: red;
}

有了这个规则,我们在初次展开treeview的时候,就需要重新制定以下数据规则。

// 省市级数据
var procityTreeData = YUNM._set.procityTreeData;
// 用户已经选中的城市,比如河南洛阳。
var init_code = $this.next("input[name=area]").val();
// 如果用户有选中项,则对选中项进行规则展示
if (init_code) {
 // 初始化选中项目
 $.each(procityTreeData, function(index, value) {
  // 通过i和省级的节点length进行对比,判断是否全选、未全选、全未选三种状态
  var i = 0;
  $.each(value.nodes, function(index1, value1) {
   if (init_code.indexOf(value1.code) != -1) {
    // 选中时先初始化state,再把state.checked设为true
    value1["state"] = {};
    value1["state"]["checked"] = true;
    i++;
   } else {
    // 否则重置state,保证procityTreeData数据的不被更改
    // 这个地方其实有待优化,由于js我还不算精通,所以不知道怎么把数组复制到一个新数组里,保证原始属于不被更改
    value1["state"] = {};
   }
  });
  value["state"] = {};
  // 市级节点有选中,那么省级节点的状态需要变化,根据上面制定的规则来
  if (i > 0) {
   // 市级全选,那么此时省级节点打钩
   if (value.nodes.length == i) {
    value["state"]["checked"] = true;
   }
   // 根据selected来设定颜色
   value["state"]["selected"] = true;
  } else {
   value["state"]["selected"] = false;
  }
 });
}

让treeview和我们打个招呼吧!

$("#procitytree").treeview({
 data : procityTreeData,// 赋值
 highlightSelected : false,// 选中项不高亮,避免和上述制定的颜色变化规则冲突
 multiSelect : false,// 不允许多选,因为我们要通过check框来控制
 showCheckbox : true,// 展示checkbox
 }).treeview('collapseAll', {// 节点展开
 silent : true
});

⑤、节点onNodeChecked、onNodeUnchecked的应用

不要⑤就够了吗?

不够,我们还要控制节点选择框的变化。

就像效果图中那样。

Bootstrap Tree View简单而优雅的树结构组件实例解析 
Bootstrap Tree View简单而优雅的树结构组件实例解析 
Bootstrap Tree View简单而优雅的树结构组件实例解析

onNodeChecked : function(event, node) {
 YUNM.debug("选中项目为:" + node);
 // 省级节点被选中,那么市级节点都要选中
 if (node.nodes != null) {
  $.each(node.nodes, function(index, value) {
   $this.treeview('checkNode', value.nodeId, {
    silent : true
   });
  });
 } else {
  // 市级节点选中的时候,要根据情况判断父节点是否要全部选中
  // 父节点
  var parentNode = $this.treeview('getParent', node.nodeId);
  var isAllchecked = true; // 是否全部选中
  // 当前市级节点的所有兄弟节点,也就是获取省下面的所有市
  var siblings = $this.treeview('getSiblings', node.nodeId);
  for ( var i in siblings) {
   // 有一个没选中,则不是全选
   if (!siblings[i].state.checked) {
    isAllchecked = false;
    break;
   }
  }
  // 全选,则打钩
  if (isAllchecked) {
   $this.treeview('checkNode', parentNode.nodeId, {
    silent : true
   });
  } else {// 非全选,则变红
   $this.treeview('selectNode', parentNode.nodeId, {
    silent : true
   });
  }
 }
},
onNodeUnchecked : function(event, node) {
 YUNM.debug("取消选中项目为:" + node);
 // 选中的是省级节点
 if (node.nodes != null) {
  // 这里需要控制,判断是否是因为市级节点引起的父节点被取消选中
  // 如果是,则只管取消父节点就行了
  // 如果不是,则子节点需要被取消选中
  if (silentByChild) {
   $.each(node.nodes, function(index, value) {
    $this.treeview('uncheckNode', value.nodeId, {
     silent : true
    });
   });
  }
 } else {
  // 市级节点被取消选中
  var parentNode = $this.treeview('getParent', node.nodeId);
  var isAllUnchecked = true; // 是否全部取消选中
  // 市级节点有一个选中,那么就不是全部取消选中
  var siblings = $this.treeview('getSiblings', node.nodeId);
  for ( var i in siblings) {
   if (siblings[i].state.checked) {
    isAllUnchecked = false;
    break;
   }
  }
  // 全部取消选中,那么省级节点恢复到默认状态
  if (isAllUnchecked) {
   $this.treeview('unselectNode', parentNode.nodeId, {
    silent : true,
   });
   $this.treeview('uncheckNode', parentNode.nodeId, {
    silent : true,
   });
  } else {
   silentByChild = false;
   $this.treeview('selectNode', parentNode.nodeId, {
    silent : true,
   });
   $this.treeview('uncheckNode', parentNode.nodeId, {
    silent : true,
   });
  }
 }
 silentByChild = true;
},

到这里,treeview的应用已经算是非常全面了

以上所述是小编给大家介绍的Bootstrap Tree View简单而优雅的树结构组件实例解析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
JS无限树状列表实现代码
Jan 11 Javascript
jQuery表单验证插件formValidator(改进版)
Feb 03 Javascript
利用jQuery的deferred对象实现异步按顺序加载JS文件
Mar 17 Javascript
Jquery显示和隐藏元素或设为只读(含Ligerui的控件禁用,实例说明介绍)
Jul 09 Javascript
javascript实用小函数使用介绍
Nov 11 Javascript
javascript如何使用bind指定接收者
May 04 Javascript
jQuery操作cookie方法实例教程
Nov 25 Javascript
属于你的jQuery提示框(Tip)插件
Jan 20 Javascript
JavaScript:Date类型全面解析
May 19 Javascript
vue引用js文件的多种方式(推荐)
May 17 Javascript
原生实现一个react-redux的代码示例
Jun 08 Javascript
vuejs实现下拉框菜单选择
Oct 23 Javascript
Angularjs为ng-click事件传递参数
Jun 15 #Javascript
详解原生js实现offset方法
Jun 15 #Javascript
微信小程序 监听手势滑动切换页面实例详解
Jun 15 #Javascript
微信小程序canvas写字板效果及实例
Jun 15 #Javascript
AngularJs实现聊天列表实时刷新功能
Jun 15 #Javascript
bootstrap daterangepicker双日历时间段选择控件详解
Jun 15 #Javascript
详解react-router如何实现按需加载
Jun 15 #Javascript
You might like
把1316这个数表示成两个数的和,其中一个为13的倍数,另一个是11的倍数,求这两个数。
2011/06/24 PHP
PHP实现合并discuz用户
2015/08/05 PHP
IE的有条件注释判定IE版本详解(附实例代码)
2012/01/04 Javascript
设置iframe的document.designMode后仅Firefox中其body.innerHTML为br
2012/02/27 Javascript
js,jquery滚动/跳转页面到指定位置的实现思路
2014/06/03 Javascript
JavaScript的面向对象编程基础
2015/08/13 Javascript
Bootstrap php制作动态分页标签
2016/12/23 Javascript
十大热门的JavaScript框架和库
2017/03/21 Javascript
原生Aajax 和jQuery Ajax 写法个人总结
2017/03/24 jQuery
详解vue组件化开发-vuex状态管理库
2017/04/10 Javascript
解决jquery appaend元素中id绑定事件失效的问题
2017/09/12 jQuery
在SSM框架下用laypage和ajax实现分页和数据交互的方法
2019/09/27 Javascript
vue之debounce属性被移除及处理详解
2019/11/13 Javascript
基于PHP pthreads实现多线程代码实例
2020/06/24 Javascript
JS实现移动端可折叠导航菜单(现代都市风)
2020/07/07 Javascript
vue实现从外部修改组件内部的变量的值
2020/07/30 Javascript
Vue实现简单的留言板
2020/10/23 Javascript
py2exe 编译ico图标的代码
2013/03/08 Python
详解python使用递归、尾递归、循环三种方式实现斐波那契数列
2018/01/16 Python
Python+PyQT5的子线程更新UI界面的实例
2019/06/14 Python
Python3 requests文件下载 期间显示文件信息和下载进度代码实例
2019/08/16 Python
python简单的三元一次方程求解实例
2020/04/02 Python
CSS3中设置3D变形的transform-style属性详解
2016/05/23 HTML / CSS
html5中使用hotcss.js实现手机端自适配的方法
2020/04/23 HTML / CSS
amazeui模态框弹出后立马消失并刷新页面
2020/08/19 HTML / CSS
医院工作检讨书范文
2014/02/10 职场文书
党的群众路线教育实践活动个人对照检查材料范文
2014/09/25 职场文书
2014年大学班长工作总结
2014/11/14 职场文书
入党宣誓仪式主持词
2015/06/29 职场文书
2015年学校政教工作总结
2015/07/20 职场文书
英语版自我评价,35句话轻松搞定
2019/10/08 职场文书
python OpenCV学习笔记
2021/03/31 Python
python使用pygame创建精灵Sprite
2021/04/06 Python
docker 制作mysql镜像并自动安装
2022/05/20 Servers
Python自动化实战之接口请求的实现
2022/05/30 Python
python playwright之元素定位示例详解
2022/07/23 Python