以下是“JavaScript树形组件实现无限级树形结构”的完整攻略。
什么是树形结构?
树形结构是计算机科学中非常常见的一种数据结构,它类似于现实生活中的树,由一个根节点和多个子节点组成。树形结构具有递归的性质,每个节点都可以看作一个子树。
树形结构在网站中的应用
在网站中,我们会经常遇到需要展示树形结构的场景,比如商品分类、组织架构、地区选择等。为了方便展示和交互,我们需要实现一个树形组件,可以无限级别地展开和收起节点。
如何实现无限级树形结构?
要实现无限级树形结构,我们需要做以下几步:
1. 准备数据
首先要准备好树形结构的数据。一个节点包含有唯一ID、父节点ID、节点名称等信息。通常,我们采用数组或者JSON格式来描述树形结构。示例数据如下:
[
{ id: 1, name: '节点1', parentId: null },
{ id: 2, name: '节点2', parentId: 1 },
{ id: 3, name: '节点3', parentId: 1 },
{ id: 4, name: '节点4', parentId: 2 },
{ id: 5, name: '节点5', parentId: 2 },
{ id: 6, name: '节点6', parentId: 4 },
{ id: 7, name: '节点7', parentId: 5 },
{ id: 8, name: '节点8', parentId: 3 }
];
2. 递归生成DOM节点
接下来,我们需要根据数据递归生成DOM节点,将节点插入到对应的父节点中。示例代码如下:
function buildTree(data, parent) {
let ul = document.createElement('ul');
parent.appendChild(ul);
data.forEach(function(node) {
if (node.parentId === parent.dataset.id) {
let li = document.createElement('li');
let title = document.createElement('div');
title.innerText = node.name;
// 点击标题展开或者收起子节点
title.onclick = function() {
li.classList.toggle('expand');
};
li.appendChild(title);
ul.appendChild(li);
buildTree(data, li);
}
});
}
let root = document.getElementById('root');
buildTree(data, root);
在上面的示例中,我们使用HTML的ul
和li
元素来实现树形结构。对于每一个节点,我们创建一个包含标题和子节点ul
的li
元素,插入到对应的父节点ul
中。通过递归调用buildTree
函数,我们可以遍历整个数据,生成完整的树形结构。
3. 添加样式和交互效果
最后,我们需要添加样式和交互效果,使树形结构更加美观和易用。比如,当用户点击标题的时候,展开或者收起相应的子节点;添加展开、收起、选中等功能按钮。
示例代码如下:
.tree li {
list-style: none;
position: relative;
padding-left: 20px;
line-height: 20px;
}
.tree li::before, .tree li::after {
content: '';
position: absolute;
left: -10px;
top: 0;
height: 100%;
border-left: 1px solid #ccc;
}
.tree li::before {
border-bottom: 1px solid #ccc;
transform: translateX(-50%);
}
.tree li::after {
transform: translateX(-50%) rotate(-90deg);
}
.tree li:last-child::before {
border-left: none;
}
.tree li.expand::after {
transform: translateX(-50%) rotate(0);
}
.tree li .btn {
position: absolute;
left: 0;
top: 0;
width: 20px;
height: 20px;
line-height: 20px;
text-align: center;
font-size: 12px;
cursor: pointer;
}
.tree li.selected {
background-color: #eee;
}
// 添加交互效果和按钮
function buildTree(data, parent) {
let ul = document.createElement('ul');
parent.appendChild(ul);
ul.classList.add('tree');
data.forEach(function(node) {
if (node.parentId === parent.dataset.id) {
let li = document.createElement('li');
let title = document.createElement('div');
title.innerText = node.name;
title.classList.add('title');
let btnExpand = document.createElement('span');
btnExpand.innerText = '+';
btnExpand.classList.add('btn', 'expand');
btnExpand.onclick = function(event) {
event.stopPropagation();
li.classList.toggle('expand');
};
title.appendChild(btnExpand);
let btnSelect = document.createElement('span');
btnSelect.innerText = '√';
btnSelect.classList.add('btn', 'select');
btnSelect.onclick = function(event) {
event.stopPropagation();
li.classList.toggle('selected');
};
title.appendChild(btnSelect);
li.appendChild(title);
ul.appendChild(li);
li.dataset.id = node.id;
buildTree(data, li);
}
});
}
let root = document.getElementById('root');
buildTree(data, root);
在上面的示例代码中,我们定义了一些CSS样式,包括节点样式、节点连接线样式、按钮样式等。而在JavaScript代码中,我们为树形节点添加了展开、收起、选中等按钮,增强了树形组件的交互体验。
树形组件的应用
实现好了树形组件,我们可以将其应用到多个场景中,比如商品分类、组织架构、地区选择等。在下面的示例中,我将演示如何使用树形组件来实现一个按地区选择的功能。
首先,我准备了一个包含省、市、区三级的地区数据。然后,我使用上面的树形组件,将地区数据转换成了树形结构,并添加了省市区三个级别的区分和选中情况的状态。
let data = [
{ code: '100000', name: '全国', type: 'COUNTRY', parentId: null },
{ code: '110000', name: '北京市', type: 'PROVINCE', parentId: '100000' },
{ code: '110100', name: '北京市', type: 'CITY', parentId: '110000' },
{ code: '110101', name: '东城区', type: 'DISTRICT', parentId: '110100' },
{ code: '110102', name: '西城区', type: 'DISTRICT', parentId: '110100' },
// ... 其他省市区数据
];
function buildTree(data, parent) {
let ul = document.createElement('ul');
parent.appendChild(ul);
ul.classList.add('tree');
data.forEach(function(node) {
if (node.parentId === parent.dataset.id) {
let li = document.createElement('li');
let title = document.createElement('div');
title.innerText = node.name;
title.classList.add('title');
let btnExpand = document.createElement('span');
btnExpand.innerText = '+';
btnExpand.classList.add('btn', 'expand');
btnExpand.onclick = function(event) {
event.stopPropagation();
li.classList.toggle('expand');
};
title.appendChild(btnExpand);
let btnSelect = document.createElement('span');
btnSelect.innerText = '√';
btnSelect.classList.add('btn', 'select');
btnSelect.onclick = function(event) {
event.stopPropagation();
li.classList.toggle('selected');
// 处理选中状态
let code = li.dataset.code;
let name = li.dataset.name;
let type = li.dataset.type;
let checked = li.classList.contains('selected');
updateSelected(code, name, type, checked);
};
title.appendChild(btnSelect);
li.appendChild(title);
ul.appendChild(li);
li.dataset.id = node.code;
li.dataset.code = node.code;
li.dataset.name = node.name;
li.dataset.type = node.type;
if (node.type === 'CITY') {
li.classList.add('city');
} else if (node.type === 'DISTRICT') {
li.classList.add('district');
}
buildTree(data, li);
}
});
}
let root = document.getElementById('root');
buildTree(data, root);
// 更新选中状态
function updateSelected(code, name, type, checked) {
console.log(`选择了 ${name}(${code}),${type},${checked}`);
}
最后的效果是一个可以实现按地区选择的树形组件,用户可以通过展开、收起、选中节点来完成地区选择操作。
示例代码可以参考以下链接:https://codepen.io/xiaolinzi/pen/zYNWAjr。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript树形组件实现无限级树形结构 - Python技术站