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 相关文章推荐
JavaScript delete操作符应用实例
Jan 13 Javascript
Firefox和IE兼容性问题及解决方法总结
Oct 08 Javascript
js原型继承的两种方法对比介绍
Mar 30 Javascript
2014年50个程序员最适用的免费JQuery插件
Dec 15 Javascript
Js的Array数组对象详解
Feb 22 Javascript
ES6中的数组扩展方法
Aug 26 Javascript
基于JS+Canves实现点击按钮水波纹效果
Sep 15 Javascript
使用elementUI实现将图片上传到本地的示例
Sep 04 Javascript
详解Vue中的基本语法和常用指令
Jul 23 Javascript
原生js实现针对Dom节点的CRUD操作示例
Aug 26 Javascript
vue 实现 rem 布局或vw 布局的方法
Nov 13 Javascript
JS函数式编程实现XDM一
Jun 16 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
php中ob(Output Buffer 输出缓冲)函数使用方法
2007/07/21 PHP
apache rewrite_module模块使用教程
2008/01/10 PHP
在smarty中调用php内置函数的方法
2013/02/07 PHP
php中\r \r\n \t的区别示例介绍
2014/02/08 PHP
PHP中遇到BOM、编码导致json_decode函数无法解析问题
2014/07/02 PHP
PHP依赖倒置(Dependency Injection)代码实例
2014/10/11 PHP
用JavaScript和注册表脚本实现右键收藏Web页选中文本
2007/01/28 Javascript
用 Javascript 验证表单(form)中的单选(radio)值
2009/09/08 Javascript
基于jquery的商品展示放大镜
2010/08/07 Javascript
根据对象的某一属性进行排序的js代码(如:name,age)
2010/08/10 Javascript
js仿土豆网带缩略图的焦点图片切换效果实现方法
2015/02/23 Javascript
jquery动态导航插件dynamicNav用法实例分析
2015/09/06 Javascript
如何解决easyui自定义标签 datagrid edit combobox 手动输入保存不上
2015/12/26 Javascript
vue-router单页面路由
2017/06/17 Javascript
JavaScript函数中的this四种绑定形式
2017/08/15 Javascript
Vue 多层组件嵌套二种实现方式(测试实例)
2017/09/08 Javascript
JS严格模式知识点总结
2018/02/27 Javascript
详解使用create-react-app快速构建React开发环境
2018/05/16 Javascript
解决Vue使用swiper动态加载数据,动态轮播数据显示白屏的问题
2018/09/27 Javascript
JavaScript 面向对象基础简单示例
2019/10/02 Javascript
用smtplib和email封装python发送邮件模块类分享
2014/02/17 Python
简单介绍Python中的floor()方法
2015/05/15 Python
Python编码爬坑指南(必看)
2016/06/10 Python
python字典DICT类型合并详解
2017/08/17 Python
Python使用functools实现注解同步方法
2018/02/06 Python
django反向解析URL和URL命名空间的方法
2018/06/05 Python
python3.x实现base64加密和解密
2019/03/28 Python
计算机二级python学习教程(2) python语言基本语法元素
2019/05/16 Python
Python 常用日期处理 -- calendar 与 dateutil 模块的使用
2020/09/02 Python
matplotlib运行时配置(Runtime Configuration,rc)参数rcParams解析
2021/01/05 Python
使用CSS3来实现滚动视差效果的教程
2015/08/24 HTML / CSS
2014国庆节幼儿园亲子活动方案
2014/09/16 职场文书
学校纪律作风整改措施思想汇报
2014/10/11 职场文书
辞职信格式模板
2015/02/27 职场文书
2015年防汛工作总结
2015/05/15 职场文书
2016年先进教师个人事迹材料
2016/02/26 职场文书