MENU
html
<template>
<div class="box">
<div class="box_content">
<p class="box_p1" @click.prevent="tabSwitch({ id: 'keyId' })">
<span :class="[queryParam.id === 'keyId' ? 'activity' : '']">全部</span>
<span>|</span>
</p>
<p class="box_p2" :class="{ activity: queryParam.id === item.id }" v-for="item in optionList"
:key="item.id" @click.prevent="tabSwitch(item)">
{{ item.name }}
</p>
</div>
<div class="go_back" v-if="showBackButton" @click.prevent="goBack">上一级</div>
</div>
</template>
JavaScript
export default {
data() {
return {
queryParam: {
id: 'keyId',
pageIndex: 1,
pageSize: 10
},
optionList: [],
previousItems: [],
lastClickTime: 0,
originList: [
{
id: 1,
pId: undefined,
name: '一级1',
child: [
{
id: 2,
pId: 1,
name: '二级1'
}
]
},
{
id: 3,
pId: undefined,
name: '一级2',
child: [
{
id: 4,
pId: 3,
name: '二级2',
child: [
{
id: 8,
pId: 4,
name: '三级1'
}
]
},
{
id: 100,
pId: 3,
name: '二级5'
}
]
},
{
id: 5,
pId: undefined,
name: '一级3',
child: [
{
id: 6,
pId: 5,
name: '二级3'
},
{
id: 9,
pId: 5,
name: '二级4'
}
]
},
{
id: 7,
pId: undefined,
name: '一级4'
},
]
}
},
computed: {
showBackButton() {
return this.previousItems.length > 0;
}
},
created() {
this.optionList = this.originList.filter(item => item.pId === undefined);
},
methods: {
findParentId(tree, currentId, parentId = undefined) {
for (let item of tree) {
if (item.id === currentId) return parentId;
if (item.child) {
let foundId = this.findParentId(item.child, currentId, item.id);
if (foundId !== undefined) return foundId;
}
}
return undefined;
},
// 返回上一级
goBack() {
let id = this.optionList[0].id;
id = this.findParentId(this.originList, id);
this.optionList = this.previousItems.pop();
this.tabSwitch({ id });
},
// 点击事件
tabSwitch(item) {
const currentTime = new Date().getTime();
const timeDiff = currentTime - this.lastClickTime;
this.lastClickTime = currentTime;
if (timeDiff <= 230) {
// 双击事件进入子菜单
if (item.child) {
this.previousItems.push(this.optionList);
this.optionList = item.child || [];
// 默认请求的id
// 可以设置为默认第一个选项
// this.queryParam.id = this.optionList[0].id;
this.queryParam.id = 'keyId';
this.search();
}
} else {
if (this.queryParam.id === item.id) return false;
// 单击事件激活tabBar
this.queryParam.id = item.id;
this.search();
}
},
search() {
console.log('发送Ajax请求... ...', this.queryParam);
}
}
}
style
.box {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
.go_back {
cursor: pointer;
margin-left: 68px;
}
.box_content {
display: flex;
.box_p1 {
display: flex;
span:first-child {
cursor: pointer;
}
span:last-child {
margin: 0 10px
}
}
.box_p2 {
cursor: pointer;
}
.box_p2:not(:last-child) {
margin-right: 10px;
}
}
}
.activity {
color: #409eff;
}
解析
一个Vue.js组件,渲染一个带有标签切换功能的菜单。
模板部分
1、使用一个外层容器div.box包裹整个组件。
2、在box内部有一个box_content容器,用于容纳标签元素。
3、使用两个span元素,第一个用于显示"全部",另一个用v-for循环渲染optionList中的元素。
4、最后,如果showBackButton为true,则显示一个"上一级"的按钮。
JavaScript部分
1、在data中定义了组件的初始数据,包括queryParam对象、optionList用于存放选项列表、previousItems用于存放历史选项列表、lastClickTime用于记录上次点击时间等。
在computed中定义了showBackButton方法,用于判断是否显示返回按钮。
3、在created钩子中初始化optionList,筛选出顶级菜单选项。
4、methods中定义了两个方法
4.1、goBack用于返回上一级菜单,将当前选项列表切换为上一次点击时存储的选项列表,并重新发送请求。
4.2、tabSwitch用于处理标签切换事件。根据点击的频率来判断是单击还是双击事件。如果是双击事件且当前点击的选项有子菜单,则将当前选项列表存入previousItems中,并将选项列表切换为点击选项的子菜单。如果是单击事件,则直接切换选项并发送请求。
样式部分
使用SCSS或者LESS预处理器语法,定义了一些样式规则,包括box和box_content的布局样式,以及活动状态的样式定义。
逻辑解释
1、组件加载时,会根据originList中的数据初始化顶级菜单选项,并将其赋值给optionList。
2、点击顶级菜单的选项会触发tabSwitch方法,根据点击频率判断是单击还是双击事件。如果是双击事件且点击的选项有子菜单,则将当前选项列表存入previousItems中,并将选项列表切换为点击选项的子菜单,并发送请求。
4、单击顶级菜单选项或子菜单选项会直接切换选项并发送请求。
5、点击返回按钮会触发goBack方法,将选项列表切换为上一级菜单,并重新发送请求。
标签:选项,菜单,name,实现,id,item,optionList,双击 From: https://blog.csdn.net/weixin_51157081/article/details/121342912pop() 方法从数组中删除最后一个元素,并返回该元素的值。此方法会更改数组的长度。