LayUI第三方组件TreeSelect下拉树实现详解
作者:橙子时间:2026-10-25 22:25:03浏览:320
本文详细介绍如何在LayUI项目中集成第三方TreeSelect组件实现下拉树功能。涵盖从引入文件、前端HTML标签配置、JS渲染逻辑,到后端Spring Boot接口返回标准JSON数据格式的完整流程,帮助开发者快速实现部门或分类的下拉选择功能。
树形结构在实际开发中是非常常用的一种数据结构。最近编写了一个基于LayUI的小案例,其中涉及到了TreeSelect组件的使用,这里将相关经验整理分享。
TreeSelect的官方文档地址为:https://fly.layui.com/extend/treeSelect/
显示效果图

由于TreeSelect并非LayUI官方原生组件,而是由第三方基于LayUI开发扩展的,因此在使用前需要正确引入相关文件。

在页面中,只需正常引入LayUI的核心CSS和JS文件即可满足基础依赖。
在页面HTML中放置一个标签元素,用于展示TreeSelect下拉树选中后的内容值。在获取选中值时,直接读取该标签的值即可得到选中的内容。
<input type="text" name="parentId" id="tree2" lay-filter="tree2" class="layui-input" />JS渲染样式代码
<script type="text/javascript">
layui.use(["treeSelect", "form", "tree"], function () {
var form = layui.form;
var tree = layui.tree;
var treeSelect = layui.treeSelect;
treeSelect.render({
// 选择器
elem: '#tree',
// 异步获取下拉树需要显示的数据
data: 'dept/treeSelect',
// 异步加载方式:get/post,默认get
type: 'post',
// 占位符
placeholder: '上级菜单',
// 是否开启搜索功能:true/false,默认false
search: true,
// 一些可定制的样式
style: {
folder: {
enable: true
},
line: {
enable: true
}
},
// 点击节点回调
click: function(d){
//console.log(d);
},
// 加载完成后的回调函数
success: function (d) {
//console.log(d);
// 选中节点,根据id筛选,一般修改时会有默认选中状态,可以在这里设置
//treeSelect.checkNode('tree', 2);
//console.log($('#tree').val());
// 获取zTree对象,可以调用zTree方法
//var treeObj = treeSelect.zTree('tree');
// console.log(treeObj);
// 刷新树结构
//treeSelect.refresh('tree');
}
});
});
</script>后台响应加载下拉树数据方法(有详细注释)
@RequestMapping(value="/treeSelect")
@ResponseBody
//这里写的,新增和修改数据请求都是同一个方法,如果是修改会传递一个修改对象的id
public Object treeSelect(Integer id) {
Sort sort = Sort.by("idx"); //排序
Specification<Dept> spec = buildSpec1(); //查询条件,查询父节点为null的元素
List<Dept> list = deptService.findAll(spec,sort); //查询,Dept为实体类
return buildTree(list, id); //转换为treeSelect指定的JSON数据格式方法
}
private Object buildTree(List<Dept> list, Integer id) {
List<HashMap<String, Object>> result=new ArrayList<>();
for (Dept dept : list) {
if(dept.getId() != id) { //判断如果是修改的话,修改的节点及下级节点不显示,也就不加载
HashMap<String, Object> node=new HashMap<>();
node.put("id", dept.getId()); //节点id
node.put("name",dept.getName()); //节点数据名称
node.put("open", false); //是否展开
node.put("checked", false); //是否选中,前台也可以设置是否选中
if(dept.getChildren().size() != 0) { //如果下级节点不为空,
node.put("children",buildTree(dept.getChildren(), id)); //递归加载下级节点
}
result.add(node);
}
}
return result;
}
public Specification<Dept> buildSpec1() {
Specification<Dept> specification = new Specification<Dept>() {
private static final long serialVersionUID = 1L;
@Override
public Predicate toPredicate(Root<Dept> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
HashSet<Predicate> rules=new HashSet<>();
Predicate parent = cb.isNull(root.get("parent")); //查询父节点为null的元素
rules.add(parent);
return cb.and(rules.toArray(new Predicate[rules.size()]));
}
};
return specification;
}Dept实体类代码
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.data.annotation.CreatedBy;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
public class Dept {
private Integer id;
private String name; //部门名称
private String deptName; //部门负责人
private String phone; //电话号
private String number; //编号
private double idx; //排序
@JsonIgnore
private Dept parent;
@JsonIgnore
private List<Dept> children = new ArrayList<>();
@Id
@GeneratedValue
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public double getIdx() {
return idx;
}
public void setIdx(double idx) {
this.idx = idx;
}
@ManyToOne
@CreatedBy
public Dept getParent() {
return parent;
}
public void setParent(Dept parent) {
this.parent = parent;
}
@OneToMany(cascade=CascadeType.ALL,mappedBy="parent")
@OrderBy(value="idx")
public List<Dept> getChildren() {
return children;
}
public void setChildren(List<Dept> children) {
this.children = children;
}
public Dept(Integer id, String name, String deptName, String phone, String number, double idx, Dept parent, List<Dept> children) {
this.id = id;
this.name = name;
this.deptName = deptName;
this.phone = phone;
this.number = number;
this.idx = idx;
this.parent = parent;
this.children = children;
}
public Dept(Integer id) {
this.id = id;
}
public Dept() {
}
}这里后台持久层使用的是Spring-Data-Jpa,如果你使用的是其他持久层框架,只要确保返回的JSON数据格式一致即可。
JSON数据格式

JSON数据
[
{
"children": [ //下级节点
{
"children": [
{
"name": "测试",
"checked": false,
"id": 30,
"open": false
}, {
"name": "开发",
"checked": false,
"id": 31,
"open": false
}, {
"children": [
{
"name": "测试节点",
"checked": false,
"id": 36,
"open": false
}
],
"name": "测试",
"checked": false,
"id": 32,
"open": false
}
],
"name": "技术部",
"checked": false,
"id": 2,
"open": false
}, {
"name": "财务部",
"checked": false,
"id": 19,
"open": false
}
],
"name": "某某公司", //节点内容
"checked": false, //是否选中
"id": 1, //id
"open": false //是否展开
}, {
"name": "测试",
"checked": false,
"id": 33,
"open": false
}
]以上为个人经验总结,希望能给大家一个参考,也希望大家多多支持本站。
作者最新文章
JS脚本在App中运行报错怎么解决
2026-11-04 23:11:03
JS怎么使用padStart方法给数字补零
2026-11-04 11:12:03
JS是什么意思?JavaScript全称及基本定义
2026-11-04 08:05:29
JS 使用 toFixed(1) 保留一位小数的基本用法与注意事项
2026-11-03 18:34:57
JS字符串转整数:parseInt与Number的区别及用法
2026-11-03 17:26:54
