<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>线性数据 转树状选择框demo</title>
<style>
* {
margin: 0;
padding: 0;
}
/* 共享部分开始 */
ul.parent {
border: 1px solid #f1f1f1;
min-width: 200px;
position: absolute;
background: #fff;
display: none;
}
ul.child {
border: 1px solid #f1f1f1;
background: #fff;
min-width: 200px;
}
ul.parent li {
list-style: none;
height: 30px;
line-height: 30px;
position: relative;
text-indent: 10px;
font-size: 14px;
cursor: pointer;
color: #000;
}
ul.parent li:hover {
background: #4471d6;
color: #fff;
}
ul.parent li > .child {
border: 1px solid #ccc;
background: #fff;
display: none;
position: absolute;
}
ul.parent li > .font_right {
float: right;
margin-right: 8px;
}
/* 共享部分结束 */
.mybox {
width: 300px;
margin: 0 auto;
}
.mySpan,
.myDiv {
display: inline-block;
width: 200px;
height: 40px;
border: 1px solid;
}
</style>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
</head>
<body>
<div class="mybox">
<div>
<input type="text" class="myInput" />
</div>
<div>
<span class="mySpan"></span>
</div>
<div>
<div class="myDiv"></div>
</div>
</div>
<script type="text/javascript">
/**
* data 渲染数据
* options doms: 回显处doms isChooseEnd: 是否选择到最末级 true必须选最末级
*/
class MyTree {
constructor(data, options, callBack) {
this.data = data
this.options = options
this.menus = '' //菜单列表html
this.callBack = callBack
}
init() {
this.renderHtml()
this.bindEvent()
}
renderHtml() {
this.GetData('', this.data)
this.options.doms.forEach((v, i) => {
v.after(this.menus)
})
}
/**
* 根据菜单主键id生成菜单列表html
* id:菜单主键id
* arry:菜单数组信息
*/
GetData(id, arry) {
var childArry = this.GetParentArry(id, arry)
if (childArry.length > 0) {
if (!!this.menus) {
this.menus += '<ul class="child">'
} else {
this.menus += '<ul class="parent">'
}
for (var i in childArry) {
var children = this.GetParentArry(childArry[i].id, arry) // 子集数组
this.menus +=
`<li data-id='${childArry[i].id}' data-name='${
childArry[i].name
}' data-isChild=${children.length > 0 ? true : false}>` +
childArry[i].name
this.menus +=
children.length > 0 ? `<span class="font_right"> > </span>` : ''
this.GetData(childArry[i].id, arry)
this.menus += '</li>'
}
this.menus += '</ul>'
}
}
/**
* 根据菜单主键id获取下级菜单
* id:菜单主键id
* arry:菜单数组信息
*/
GetParentArry(id, arry) {
var newArry = new Array()
for (var i in arry) {
if (arry[i].pid == id) newArry.push(arry[i])
}
return newArry
}
bindEvent() {
var self = this
// 鼠标移入时增加标识show并且其它子元素的child隐藏 自己的显示
$('ul.parent li').on('mouseenter', function(e) {
$(this)
.addClass('show')
.siblings()
.children('.child')
.hide()
$(this)
.children()
.css({ left: $(this).width(), top: '-1px' })
.show()
})
// 同级别li相互切换时只能保留一个选中状态
$('ul.parent li').on('mouseleave', function() {
$(this).removeClass('show')
})
// 移出主数据框消失
$('ul.parent').on('mouseleave', function() {
$(this)
.parent()
.css('position', 'inherit')
$('.child').hide()
$('.parent').hide()
})
// 移出子集框该子集消失
$('ul.child').on('mouseleave', function() {
$(this)
.parent('.parent')
.parent()
.css('position', 'inherit')
$(this)
.hide()
.children()
.removeClass('show')
})
// 选择时得到结果
$('ul.parent li').on('click', function(e) {
var nameArr = []
var idArr = []
if (self.options.isChooseEnd) {
if ($(this).data('ischild')) {
return false
}
}
$('.show').each((i, v) => {
nameArr.push($(v).data('name'))
idArr.push($(v).data('id'))
})
// 将数据回显到传值处
if (
$(this)
.closest('.parent')
.siblings()[0].tagName == 'INPUT'
) {
$(this)
.closest('.parent')
.siblings()
.val(nameArr.join('>'))
.attr('title', nameArr.join('>'))
} else {
$(this)
.closest('.parent')
.siblings()
.text(nameArr.join('>'))
.attr('title', nameArr.join('>'))
}
$(this)
.closest('.parent')
.parent()
.css({ position: 'inherit' })
$('.child').removeClass('show')
$('.parent').hide()
// 如果有回调函数
if (self.callBack) {
self.callBack({
nameArr: nameArr,
idArr: idArr,
dom: $(this)
.closest('.parent')
.siblings()
})
}
e.stopPropagation()
e.preventDefault()
})
// 传入的dom点击事件
self.options.doms.forEach((v, i) => {
v.on('click', function(e) {
$(this)
.siblings('.parent')
.show()
.parent()
.css({ position: 'relative' })
})
})
}
}
$(function() {
var data = [
{ id: '001', name: '办公管理办公管理办公管理办公管理', pid: '' },
{ id: '002', name: '请假申请', pid: '001' },
{ id: '003', name: '出差申请', pid: '001' },
{ id: '004', name: '请假记录', pid: '002' },
{ id: '005', name: '系统设置', pid: '' },
{ id: '006', name: '权限管理', pid: '005' },
{ id: '007', name: '用户角色', pid: '006' },
{ id: '008', name: '菜单设置', pid: '006' },
{ id: '009', name: '测试数据1', pid: '007' },
{ id: '010', name: '测试数据2', pid: '007' }
]
var mytree = new MyTree(
data,
{
doms: [$('.myInput'), $('.mySpan'), $('.myDiv')],
isChooseEnd: true // 是否只能选择到最末级
},
function(res) {
console.log('回调值:', res)
}
)
mytree.init()
})
</script>
</body>
</html>
效果图如下
![效果图](https://images.cnblogs.com/cnblogs_com/yzyh/1334873/o_200307065601%E6%95%88%E6%9E%9C%E5%9B%BE.png)