下面为大家详细讲解 JavaScript 几种形式的树结构菜单的完整攻略。
下面为大家详细讲解 JavaScript 几种形式的树结构菜单的完整攻略。
什么是树结构菜单
树结构菜单是一种常见的用于网站导航或者分类展示的组件。树结构菜单的特点是可以展开、收起某一层级的菜单,同时高亮显示当前选中的菜单项。在前端开发中,我们可以使用 JavaScript 来实现这种树状结构的菜单。
JavaScript 实现树结构菜单的基本思路
在使用 JavaScript 实现树结构菜单的过程中,我们需要先获取到数据,然后根据数据生成对应的 HTML 元素,最后实现菜单的展开和收起效果。具体实现的流程如下:
1.定义数据结构: 利用JS对象来描述树形结构,例如:
let treeData = [
{
name: '菜单1',
children: [
{ name: '菜单1.1', children: [] },
{ name: '菜单1.2', children: [] }
]
},
{
name: '菜单2',
children: [
{ name: '菜单2.1', children: [] },
{ name: '菜单2.2', children: [] }
]
}
]
2.将树形结构转化为HTML结构,使用递归的方式遍历对象树,将对象属性渲染为HTML的列表项,如下所示:
function renderTree(data) {
let ul = document.createElement('ul')
data.forEach(item => {
let li = document.createElement('li')
li.innerHTML = item.name
if(item.children && item.children.length) {
li.appendChild(renderTree(item.children))
}
ul.appendChild(li)
})
return ul
}
3.绑定事件并实现菜单展开和收起效果,通过添加CSS类名来实现展开和收起菜单的效果,例如:
function initTree() {
let root = document.querySelector('.tree')
let tree = renderTree(treeData)
root.appendChild(tree)
// 绑定点击事件
root.addEventListener('click', e => {
let target = e.target
if(target.tagName === 'LI' && target.children.length) {
target.classList.toggle('open')
}
})
}
通过以上步骤,我们就可以实现一个基本的树状结构菜单。
JavaScript 实现树结构菜单的多种形式
除了基本的树状结构菜单,还可以实现以下两种形式:
1. 滑动展开效果
实现方法是:利用 CSS3 的 transition 属性给菜单添加滑动效果。
具体实现示例可以参考:https://codepen.io/eFishery/pen/VYJXGo
// JS 代码
let toggleEl = document.querySelectorAll('.tree-toggle');
let i;
for (i = 0; i < toggleEl.length; i++) {
toggleEl[i].addEventListener('click', function(e) {
e.preventDefault();
let treeMenu = e.target.parentElement; //去掉最后一级的a标签
let treeChild = treeMenu.childNodes[3];
treeChild.classList.toggle('d-none');
e.target.classList.toggle('fa-plus');
e.target.classList.toggle('fa-minus');
});
}
// CSS 代码
.tree-menu {
list-style-type: none;
margin: 0;
padding: 0;
padding-left: 20px;
}
.tree-menu li {
position: relative;
margin: 0;
padding: 0;
list-style: none;
}
.tree-toggle {
cursor: pointer;
display: inline-block;
}
.d-none {
display: none;
}
.fa-minus {
display: none;
}
a > .fa-plus:before {
content: "\\f067";
}
a > .fa-minus:before {
content: "\\f068";
}
a:focus {
outline: none;
}
.tree-menu li > .fa {
position: absolute;
left: -12px;
top: 50%;
margin-top: -10px;
}
.tree-menu > li > .fa {
position: absolute;
left: 0;
top: 50%;
margin-top: -10px;
}
.tree-menu li > ul {
display: none;
}
.tree-menu li > ul.d-none {
display: block;
}
.tree-menu li > ul {
margin-top: 10px;
}
.tree-menu li > ul:before {
content: '';
display: block;
border-left: 1px solid #ccc;
bottom: 0;
left: -20px;
position: absolute;
top: 0;
}
2. 搜索筛选效果
实现方法是:利用输入框输入关键词后,自动过滤不包含此关键词的菜单项。
具体实现示例可以参考:https://codepen.io/pokaworks/pen/BWYZzy
// JS 代码
// 输入框变化时执行
function onSearch(event) {
// 搜索关键字
// toLowerCase() 转换为小写,方便比较
let keyword = event.target.value.trim().toLowerCase();
// 从内存获取数据
// 然后更新可见数据节点
let searchRst = Search(keyword)
if (searchRst) {
$('#tree').empty();
$('#tree').append(RenderVisible(searchRst));
ExpandNode(event.target.value.trim());
}
}
// 初始渲染visibleNodes
function RestoreNodes() {
visibleNodes = [];
visitedNodes = [];
function Follow(node) {
// 如果没访问过当前节点
if (!visitedNodes[node.id]) {
visitedNodes[node.id] = true;
// 如果该节点包含我要的关键字
if (node.title.toLowerCase().indexOf(this.keyword) > -1) {
visibleNodes.push(node.id);
ExpandParents(node.parentId);
}
// 深度优先遍历子节点
node.children.forEach(Follow, this)
}
}
this.keyword = '';
treeData.forEach(Follow, this)
return visibleNodes;
}
// 根据visibleNodes筛选节点
function RenderVisible(visibleNodes) {
function Follow(node) {
if (visibleNodes.indexOf(node.id) > -1) {
results.push(node);
}
}
var results = [];
treeData.forEach(Follow);
return SortNode(results);
}
// HTML 代码
<div class="form-group">
<input type="text"
class="form-control"
placeholder="输入内容并回车搜索"
onblur="RestoreAll();"
onkeyup="OnSearch(event);"/>
</div>
<div id="tree"></div>
<script>
$("#tree").append(RenderVisible(RestoreNodes()));
</script>
总结
通过以上的示例,我们可以看到,实现树状结构菜单的效果并不难,但其中涉及到的细节还是很多的,需要我们仔细斟酌。实际开发中,我们可以根据项目需要,选择不同的实现方式,以达到最佳效果。
本文标题为:JavaScript几种形式的树结构菜单
基础教程推荐
- js变换显示图片的实例 2024-01-07
- js操作输入框提示信息且响应鼠标事件 2024-01-09
- 纯JS实现AJAX局部刷新功能 2023-01-31
- Vue简单到复杂,了解到熟悉 2023-10-08
- 全面解析$.Ajax()方法参数(推荐) 2023-01-20
- react vue 等等这种mvvm思维的开发方式怎么编写通用组件,或者什么样的组件应该编写为通用组件 2023-10-08
- JS函数验证总结(方便js客户端输入验证) 2024-01-03
- Vue中自动化引入样式及组件样式穿透 2023-10-08
- 通过Ajax方式上传文件使用FormData进行Ajax请求 2023-01-20
- JavaScript实现放大镜效果 2023-08-08