这一节我们来讲一下面包屑导航的问题。
先看思路,当我们点击左侧的一级课程,是不是可以拿到一个ID?
这个ID的作用可大了,我们有了这个ID,本意是通过它去寻找它所有的子节点。
看图,假设【JAVA基础】里面有JDK,Hello,变量三个课程。那么请问,这三个课程的PID(父节点)是不是就正好等于【JAVA基础】的ID呢。
对了,就是这么个思路。这样一来,二级分类的数据我们就拿到了。
下一个问题,假如是三级分类呢?
先导一下数据:
INSERT INTO `edu`.`type` (`id`, `level`, `pid`, `type_name`, `order_num`) VALUES ('402880e876f69e280176f6a731a20001', '2', '402880e876f69e280176f6a731a20000', 'JDK安装', '1'); INSERT INTO `edu`.`type` (`id`, `level`, `pid`, `type_name`, `order_num`) VALUES ('402880e876f69e280176f6a731a20002', '2', '402880e876f69e280176f6a731a20000', 'eclipse的使用', '2'); INSERT INTO `edu`.`type` (`id`, `level`, `pid`, `type_name`, `order_num`) VALUES ('402880e876f69e280176f6a731a22001', '3', '402880e876f69e280176f6a731a20001', '下载JDK', '1');
看图,假设【JAVA基础】里面有JDK,Hello,变量三个课程。那么请问,这三个课程的PID(父节点)是不是就正好等于【JAVA基础】的ID呢。
对了,就是这么个思路。这样一来,二级分类的数据我们就拿到了。
下一个问题,假如是三级分类呢?
先导一下数据:
INSERT INTO `edu`.`type` (`id`, `level`, `pid`, `type_name`, `order_num`) VALUES ('402880e876f69e280176f6a731a20001', '2', '402880e876f69e280176f6a731a20000', 'JDK安装', '1'); INSERT INTO `edu`.`type` (`id`, `level`, `pid`, `type_name`, `order_num`) VALUES ('402880e876f69e280176f6a731a20002', '2', '402880e876f69e280176f6a731a20000', 'eclipse的使用', '2'); INSERT INTO `edu`.`type` (`id`, `level`, `pid`, `type_name`, `order_num`) VALUES ('402880e876f69e280176f6a731a22001', '3', '402880e876f69e280176f6a731a20001', '下载JDK', '1');
现在的关系图如下:
面包屑是啥东东呢,比如你点的是Java基础,那么面包屑就是 Java基础。
你点JDK安装,面包屑就是 Java基础 | JDK安装。
你点下载JDK,面包屑就是 Java基础 | JDK安装 | 下载JDK
反正我就是这么理解的。
于是乎,我们就得写一个方法,递推出当前节点上面所有的父节点。
查询方法代码如下:
/** * 查询分类 * @param type * @return */ @RequestMapping("/list") @ResponseBody public Map<String,Object> list(Type type){ Map<String,Object> result = new HashMap<>(); result.put("code",0); //如果id为空,说明是加载一级课程分类 if(type.getId() == null){ type.setPid("0"); //我们规定一级分类的父ID是0 }else{ //如果有ID传过来,就看做是PID,去查询它所有的子节点 String pid = type.getId(); Type probe = new Type(); probe.setPid(pid); //查询条件就是pid List<Type> childTypes = typeDao.findAll(Example.of(probe)); //子节点查询完毕 result.put("childTypes",childTypes); //根据本次点击的分类,向上追溯父节点 List<Type> listTypeForBread = new ArrayList<Type>(); //因为前台只传过来ID,所以要去数据库搜索完整的Type type = typeDao.findOne(type.getId()); //本次点击的节点肯定要加进去 listTypeForBread.add(type); getParents(listTypeForBread,type); for (Iterator iterator = listTypeForBread.iterator(); iterator.hasNext();) { Type type2 = (Type) iterator.next(); System.out.println(type2.getTypeName()); } } List<Type> findByPid = typeDao.findByPid(type.getPid()); result.put("data", findByPid); return result; }
追溯所有父节点,我单独封装了一个方法。
//追溯所有父节点 private void getParents(List<Type> listTypeForBread, Type type) { //如果父节点是0,说明是点击一级菜单而已,直接返回一级菜单就行了。 if(type.getPid().equals("0")){ return; } Type probe = new Type(); probe.setId(type.getPid()); Type parent = typeDao.findOne(Example.of(probe)); listTypeForBread.add(parent); if(parent.getPid().equals("0")){ return; } getParents(listTypeForBread,parent); }
验证一下代码的逻辑,新建一个测试方法。
Java进阶的ID是402880e876f69e280176f6a731a20000,我们就用它来测试:
@Test public void listType(){ Type type = new Type(); type.setId("402880e876f69e280176f6a731a20000"); typeController.list(type); }
测试结果:
接着用402880e876f69e280176f6a731a20001,402880e876f69e280176f6a731a22001来测试,分别对应JDK安装和下载JDK,是二级分类和三级分类。
结果:
顺序倒过来了,没关系,我们再修改一下list方法。
//list倒序 List<Type> listTypeForBreadNew = new ArrayList<>(); for (int i = listTypeForBread.size() - 1; i >= 0 ; i--) { Type typeItem = listTypeForBread.get(i); listTypeForBreadNew.add(typeItem); } //面包屑数据处理完毕 result.put("breadList",listTypeForBreadNew);
这样就完成了倒序,虽然代码不够精美,但是能用。
数据没问题了,就去搞搞页面吧。
ElementUI已经给我们提供了面包屑的组件了,直接拿来用。
最终代码:
/* 改变面包屑导航的字体颜色 */ .el-breadcrumb__item a { color:#1989fa !important; } .el-breadcrumb { font-size: 14px; line-height: 1; background: #e3f3d1; padding: 14px 8px; border-radius: 2px; border-color: #e3f3d1; }
下面这段代码比较复杂,我踌躇再三才决定这么写的。如果你有更好的办法,可以私信我,我可以抄袭,哦不,借鉴一下。
<el-breadcrumb separator="/" style="margin-bottom: 10px;"> <el-breadcrumb-item><a href="${basePath}/admin/index">首页</a></el-breadcrumb-item> <el-breadcrumb-item v-for="(item,index) in breadList"> <a :style="index == breadList.length - 1 ? 'color:#777 !important;': '' " :href=" index == breadList.length - 1 ? 'javaScript:void(0)' : '${basePath}/type/list?id=' + item.id"> {{item.typeName}} </a> </el-breadcrumb-item> </el-breadcrumb>
先看最终效果:
然后是遍历二级课程,这可真TM要了我的老命,很绕啊,我也试了很多办法才搞出来的。
代码如下:
<el-row :gutter="20" v-for="(row,rowIndex) in childTypes" style="margin:30px 16px;"> <el-col :span="6" v-for="(item,colIndex) in childTypes[rowIndex]" > <el-badge :value="'9'" class="item"> <el-card class="box-card" shadow="hover" style="height:150px;" body-style=""> <div slot="header" class="clearfix card-header"> <span><i class="el-icon-document"></i></span> <div class="cardname" type="text">[{{item.typeName}}]</div> </div> <div class="text item"> [{{item.typeName}}] </div> <span class="ordernum">{{rowIndex * 4 + colIndex+1}}</span> </el-card> </el-badge> </el-col> </el-row>
代码不多,但是还真的挺难想的,也许是我太菜了,哈哈哈。
效果:
对应的JS代码:
//循环次数 that.loop = data.childTypes.length / 4 + 1; //本次加载的所有同级分类 that.typesMain = data.data; //面包屑 that.breadList = data.breadList; //子节点数据 var childTypes = data.childTypes; //处理子节点,每四个一组(难点) var arr = []; //debugger; var count = Math.floor(childTypes.length / 4) + 1; for(var i = 0;i < count;i++){ //每次循环都要用到一个新的数组 var newArr = JSON.parse(JSON.stringify(childTypes)); var start = i * 4; if( i == count - 1){ arr[i] = newArr.splice(start) }else arr[i] = newArr.splice(start,4) } that.childTypes = arr; console.log(that.childTypes);
代码很多,我只贴了关键部分,需要完整源码的可以关注【java小白翻身】,加群获取。
哎,累死了,我下班后一直写到现在,跪求一键三联啊,分享一波,您的支持是我最大的动力。