记一次Vue跨导航栏问题解决方案
简述
这篇文章是我项目中,遇到的一个issue,我将解决过程和方法记录下来。
本篇文章基于Vue.js进行的前端页面构建,由于仅涉及前端,将不做数据来源及其他部分的叙述。使用的CSS框架是 BootstrapVue 和 Element-UI 。数据使用 json 文件进行模拟,数据可在文章末的链接源码中查看
需求描述
项目需求是实现双导航栏:顶部导航栏和侧边导航栏。顶部导航栏用于展示一级菜单,根据点击的不同一级菜单,在屏幕左侧展示不同的二级三级导航栏。要求当前页面导航栏菜单需要高亮。
需求分析
数据,json 文件使用axios进行获取,然后赋值给Home.vue下的menus变量,再分发到Nav.vue中,进行一级导航的展示。默认情况下,高亮第一个一级菜单。如果该一级菜单下没有二级菜单和三级菜单,则不显示左侧导航栏,如果有,则展示。当点击了一级菜单时,默认页面展示该菜单下的第一个菜单的页面。
例如:点击了第一个菜单,这个菜单有二级,三级菜单,则展示该菜单下的三级菜单的页面,如果没有三级菜单,则展示二级菜单的页面,如果没有二级菜单,则展示一级菜单的页面。
默认情况下,渲染完成侧边导航栏后高亮导航栏的第一个最下级菜单
主要代码结构

遇到的问题
1、父组件与子组件相互传值
父组件传值给子组件(Home.vue,父):
父组件传值个子组件(myNav.vue,子)
子组件通过props进行数据的接收,该属性是一个数组的形式,父组件通过绑定的形式直接给组件的属性赋值便可实现父组件向子组件传值。
子组件传值给父组件(myNav.vue 子):
子组件传值给父组件(Home.vue 父):
父组件传值给子组件与子组件传值给父组件不同,父组件需要对自定义事件进行监听,而子组件需要触发该事件才能够通过$emit进行传值,在父组件中,传值的接收变量名固定为$event,不能使用其他名字进行获取数据。
2、顶部导航栏的高亮问题
因为顶部导航栏使用的是Bootstrap-Vue框架,所以高亮菜单时只需加上class:active便可以使其高亮,问题是根据需求,高亮的控制权交由父组件Home.vue,而不在子组件myNav.vue中完成,这也就涉及到了刚刚说的组件传值的问题,上述已经叙述过组件传值的问题,此处仅简述其逻辑。
子组件中绑定点击事件后,会将点击的一级菜单的ID值传给父组件。由于原需求中,可能会涉及到URL跳转到任意页面,所以,根据this.$route.path来判断是哪一个页面,再将这个页面的ID值传回给子组件。
传回后使用三元运算符,来比对是否与渲染时id匹配,若匹配,则高亮

3、左侧导航的高亮问题
需求重述:
点击一级菜单,若该菜单数据中存在二级菜单,则在左侧导航栏中显示,如不存在,则隐藏左侧导航栏。默认情况下,若该一级菜单有下属三级子菜单,则跳转第一个下属二级子菜单下的第一个下属三级菜单;若没有三级菜单,则跳转第一个下属二级子菜单的URL;若没有下属二级子菜单,则跳转至一级的URL。在此基础上,高亮当前的菜单。
与顶部导航栏不同,顶部导航栏的高亮是依靠菜单的点击和路由来控制,而侧边导航栏使用的是element-UI的导航栏,根据default-active进行高亮。
default-active的原理是该属性的值与菜单中的index进行比较,若相等则高亮。原理很简单,但是实现起来却没有那么容易。
第一次解决方案:在点击一级菜单时,上述已经说过,将id值传给父组件Home.vue中。父组件监听到该事件触发后,遍历之前通过axios获取到的数据,最终找到匹配的一级菜单,进而判断该菜单下是否有二级乃至三级菜单,若有,则显示第一个,并且将该属性的url值赋值给上述的default-active。
从原理的角度来说,该思想没有问题。可是该方法会导致一个问题,在进入页面后,点击任何一级菜单都能够正常生效,但是互相点击时,左侧导航不显示高亮,页面能够正常跳转。
例如:进入到该页面后,第一次点击任何一级菜单都没有问题,正常显示。在第二次点击任何菜单时均没有高亮显示。
在模拟数据中,有一个一级菜单没有下属菜单,若第一次点击除此菜单以外的菜单时,均可正常显示。第二次若点击除此菜单以外的菜单时,并不会高亮。
我想说的是,若第二次点击的是这个没有下属菜单的一级菜单,第三次再去点任意菜单,又可以正常显示了。
对于这个问题,至少在我看来觉得是很神奇的。于是我将这个操作模拟到每一次的页面点击中,也就是任何一次点击都做一次向那个没有数据的菜单来一次跳转,再跳转回来,发现问题解决了。
那么问题出现在哪里,应该怎样解决,总不至于,每次跳转都需要经过那个没有下属菜单的页面吧,数据是动态的,并不清楚哪个一级菜单没有下属页面菜单。
分析
跳转至无下属菜单的一级菜单时,做了两件事,1:将侧边导航栏数据清空,2:隐藏侧边导航栏。
跳转至其他菜单时,也做了两件事,1:重新赋值侧边导航栏,2:显示侧边导航栏。
首先排除隐藏/显示导航栏,样式的修改,应该不至于会出现这种问题。(其实我也偷偷试过。。)
接下来就只剩下赋值和清空数据了
该代码如下
click1thMenu (id) {
this.menus2th = []
this.active1thMenu = id
for (let i = 0; i < this.menus.length; i++) {
if (this.menus[i].id === id) {
if (this.menus[i].child !== undefined) {
this.asideWidth = '200px'
this.menus2th = this.menus[i].child
} else {
this.asideWidth = '0'
}
}
}
}
我的代码逻辑中,不管是赋值还是情况操作都会将数据清空。到这里,问题就扑朔迷离了。
好了,不卖关子了,直接说结果
我思考,会不会因为在有下属菜单的情况下,清空语句执行后再执行赋值语句,会导致情况语句成为无用代码,被浏览器直接优化掉了,于是我在赋值语句上加了一个延时函数,给他一定的延时。
methods: {
click1thMenu (id) {
this.menus2th = []
this.active1thMenu = id
for (let i = 0; i < this.menus.length; i++) {
if (this.menus[i].id === id) {
if (this.menus[i].child !== undefined) {
this.asideWidth = '200px'
setTimeout(() => {
this.menus2th = this.menus[i].child
}, 10)
} else {
this.asideWidth = '0'
}
}
}
}
然后发现问题就解决了,如果有明白这个原理的大神,也欢迎在下面留言讨论
源码地址:https://gitee.com/handsky/vue-nav
记一次Vue跨导航栏问题解决方案的更多相关文章
- 超详细Vue实现导航栏绑定内容锚点+滚动动画+vue-router(hash模式可用)
超详细Vue实现导航栏绑定内容锚点+滚动动画+vue-router(hash模式可用) 转载自:https://www.jianshu.com/p/2ad8c8b5bf75 亲测有效~ <tem ...
- 使用vue给导航栏添加链接
如下面的导航栏,使用vue技术给该导航栏增加链接: js代码为: navigation:function(){ new Vue({ el: '#navUl', data: { menuData:{ ' ...
- Nuxt/Vue自定义导航栏Topbar+标签栏Tabbar组件
基于Vue.js实现自定义Topbar+Tabbar组件|仿咸鱼底部凸起导航 最近一直在倒腾Nuxt项目,由于Nuxt.js是基于Vue.js的服务端渲染框架,只要是会vue,基本能很快上手了. 一般 ...
- Vue设置导航栏为公共模块并在登录页不显示
1.公共模块的内容可以放在App.vue中但是通常登录页面是不需要导航的,那么就需要规避登录页这时,就可以采用keep-alive结合$route.meta来实现这个功能.keep-alive 是 V ...
- vue 侧边导航栏递归显示
import axios from "axios"; import tabs1 from "../tab_content/tab1.vue"; import m ...
- vue组件导航栏动态添加class
- 用Vue来实现音乐播放器(五):路由配置+顶部导航栏组件开发
路由配置 在router文件夹下的index.js中配置路由 import Vue from 'vue' import Router from 'vue-router'//配置路由前先引入组件impo ...
- ElementUI+命名视图实现复杂顶部和左侧导航栏
在了解了命名视图的用途后,发现用命名视图来实现复杂导航更加省力.更多知识请参考这里 这里只说明重要配置内容,其他内容配置请参考上一篇初始版本: ElementUI 复杂顶部和左侧导航栏实现 或参考文末 ...
- 使用vue封装一个tab栏切换的左侧导航栏的公共组件
首先看最终效果图: 1.compent文件夹里添加tab文件夹,里面创建index.vue index.js index.css index.vue内的template部份代码如下:(最新更正:代码 ...
随机推荐
- .NET平台系列30:.NET Core/.NET 学习资源汇总
系列目录 [已更新最新开发文章,点击查看详细] .NET Core/.NET技术虽然吸取了.NET Framework 中的精华,但是也扩展了一些新功能,尤其是跨平台的 ASP.NET Cor ...
- 「10.17-10.18」liu_runda’s模拟
暂咕 $day1$ A. 位运算 分类讨论,贡献分离. B. 集合论 维护类似时间戳的东西 C. 连连看 考场思路太局限了,考虑容斥. 我们可以看出两个方块能作出贡献,实际上是一个极大联通块(白块)所 ...
- 【题解】Grape luogu1156改 dp
考试时被数据坑了 题目 原题 传送门 题目描述: 众所周知的是oyyf 沉迷葡萄,今天的oyyf为了葡萄溜到了He 大佬家的葡萄园偷葡萄,可惜的是还没偷到葡萄He 大佬就来葡萄园了,吓的oyyf 直接 ...
- Unreal如何进行材质优化?
Hello,大家好,今天给大家带来实用的材质优化,我是木偶心没.优化在每个游戏项目里面都会涉及到,是一种为了达成相同目标,寻求并采用消耗更少资源的办法.一般会在CPU,GPU,网络和内存方便进行优化. ...
- SpringCloud+Docker+Jenkins+GitLab+Maven实现自动化构建与部署实战
1.前言与初衷 本文章会涉及Docker常见命令基础知识点结合不同场景实操一起使用. 本文章会涉及结合工作过程中部署不同环境服务器的项目案例场景为初心进行实际细讲. 本文章主要讲述Docker.Jen ...
- CVPR2021|一个高效的金字塔切分注意力模块PSA
前言: 前面分享了一篇<继SE,CBAM后的一种新的注意力机制Coordinate Attention>,其出发点在于SE只引入了通道注意力,CBAM的空间注意力只考虑了局部区域的信息 ...
- 带你掌握C++中三种类成员初始化方式
摘要:在C++11之后,声明时初始化->初始化列表->构造函数初始化. 本文分享自华为云社区<如何编写高效.优雅.可信代码系列(3)--类成员初始化的三种方式>,原文作者:我是 ...
- qemu-ga windows下的安装及监控开发
windows安装qemu-ga 虚拟机配置里添加virtio serial端口 #virsh edit instance-name devices里添加下面这段配置, 1 <channel t ...
- Maven安装、配置及基础
简介: Maven是Apache公司的开源项目,是项目构建工具,用来管理依赖. Maven的优点: 同样的代码实现相同的功能,Maven项目没有Jar包,项目大小更小. maven的优点如何实现: 没 ...
- ExtJs4学习(五)最基本的Ext类
Ext类是ExtJs中最常见.最基础的一个类,它是一个全局对象,封装了所有类.单例和 Sencha 库所提供的实用方法. 大多数用户界面组件在一个较低的层次嵌套在命名空间中, 但是提供的许多常见的实用 ...





