按箭头上下左右来实现简单二层级树形结构
.vue template内容
<div class="nav-container">
<ul class="nav-list" :class="{ 'border-glow': status == 'F' }">
<li
v-for="(item, index) in items"
:key="index"
@click="selectItem(index)"
:class="{ active: activeIndex === index }"
>
{{ item.name }}
<ul
v-if="isVisible(index)"
:class="[
isVisible(index) ? 'children-selected' : 'children',
status == 'C' ? 'border-glow' : '',
]"
>
<li
v-for="(child, ind) in item.children"
@click="selectChildrenItem(ind)"
:key="ind"
:class="{ active: activeChildrenIndex === ind }"
>
{{ child.name }}
</li>
</ul>
</li>
</ul>
</div>
script中内容
export default {
data() {
return {
activeIndex: 0, // 用于跟踪当前展开的子列表的父项索引
activeChildrenIndex: 0,
status: "F",
items: [
{
name: "站点1",
hasChildren: true,
children: [
{
id: 1,
name: "10kV"
},
{
id: 2,
name: "20kV"
},
],
},
{
name: "站点2",
hasChildren: false
},
{
name: "站点3",
hasChildren: false,
},
{
name: "站点4",
hasChildren: false
},
],
};
},
methods: {
selectItem(index) {
this.activeIndex = index;
},
selectChildrenItem(index) {
this.activeChildrenIndex = index;
},
isVisible(index) {
// 根据activeIndex判断当前项的子列表是否应该显示
return this.activeIndex === index;
},
handleKeyDown(event) {
const length = this.items.length ? this.items.length : 0;
const currentItem = this.items[this.activeIndex];
const childrenLength =
currentItem && Array.isArray(currentItem.children)
? currentItem.children.length
: 0;
// 根据按键来移动当前索引
if (event.key === "ArrowDown") {
if (this.status == "F") {
this.activeIndex = (this.activeIndex + 1) % length;
} else {
if (length > 0) {
this.activeChildrenIndex =
(this.activeChildrenIndex + 1) % childrenLength;
}
}
} else if (event.key === "ArrowUp") {
if (this.status == "F") {
this.activeIndex = (length + this.activeIndex - 1) % length;
} else {
this.activeChildrenIndex =
(childrenLength + this.activeChildrenIndex - 1) % childrenLength;
}
} else if (event.key === "ArrowLeft") {
// 选中父列表状态为F,选中子列表状态为C
if ((this.status = "C")) {
this.status = "F";
// 让子项归为0
this.activeChildrenIndex = 0;
// 加入选中样式
}
} else if (event.key === "ArrowRight") {
event.preventDefault();
if ((this.status = "F")) {
this.status = "C";
// 加入样式
}
} else if (event.key === "Enter") {
this.$router.push({
path: "xxx",
});
}
// 可以根据需要添加ArrowLeft等其他按键处理
}
},
mounted() {
// 监听键盘事件
document.addEventListener("keydown", this.handleKeyDown);
},
beforeDestroy() {
// 移除事件监听器
document.removeEventListener("keydown", this.handleKeyDown);
},
};
style
.item {
position: relative; /* 使得子列表可以相对于父项定位 */
display: flex; /* 使用flex布局来让文本和箭头/按钮并排显示 */
align-items: center; /* 垂直居中 */
/* 其他样式... */
}
/* 隐藏默认的下拉列表样式(如果需要的话) */
.children {
display: none;
}
/* 当子列表应该显示时,使用CSS类来覆盖上面的display: none */
.children-selected {
display: block; /* 或者使用flex、grid等其他布局方式 */
position: absolute;
background-color: #142bf7b6;
left: 50%;
width: 200px;
height: auto;
}
/* 隐藏默认的下拉列表样式(如果需要的话) */
.childrenD {
display: none;
}
/* 当子列表应该显示时,使用CSS类来覆盖上面的display: none */
.childrenD-selected {
display: block; /* 或者使用flex、grid等其他布局方式 */
position: absolute;
background-color: #142bf7b6;
left: 100%;
width: 200px;
height: auto;
}
.nav-container {
display: flex;
width: 25%;
list-style: none;
padding: 0;
margin: 10% 0 0 25%;
}
.nav-list {
flex: 1;
}
.nav-list li {
padding: 10px;
font-size: 18px;
border: 1px solid rgba(204, 204, 204, 0.014);
margin-bottom: -1px; /* 移除相邻元素之间的双边框 */
cursor: pointer;
background-color: #6eb6f1a6;
}
.nav-list li.active {
font-size: 18px;
background-color: #064ccf;
color: white;
}
.border-glow {
/* 使用CSS来创建发光效果 */
border: 2px solid #42b983; /* 举例:绿色边框 */
box-shadow: 0 0 10px #42b983; /* 举例:绿色发光效果 */
}