记一次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部份代码如下:(最新更正:代码 ...
随机推荐
- 尚硅谷Java——宋红康笔记【day19-day24】
day19 测试Thread中的常用方法: start():启动当前线程:调用当前线程的run() run(): 通常需要重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中 curr ...
- 2、java基础语法(上):变量与运算符
关键字与保留字 关键字 定义:被Java语言赋予了特殊含义,用做专门用途的字符串(单词) 特点:关键字中所有字母都为小写 官方地址:https://docs.oracle.com/javase/tut ...
- 08:'my_tag' is not a registered tag library. Must be one of
确保每次修改模板标签时都重新启动 Django 开发服务器(或确保它自己重新启动).如果服务器没有重新启动,Django 将不会注册标签. 从 django 1.9 开始,您可以在如下设置中加载这些新 ...
- 从 Nginx 优秀的核心架构设计,揭秘其为何能支持高并发?
目录: 1. Nginx的整体架构 2. Nginx的模块化设计 3. Nginx的请求方式处理 4. Nginx事件驱动模型 5. Nginx进程处理模型 写在前面 Nginx 是一个 免费的,开源 ...
- git stash回退
目录 1.起因 2. 问题出现 3.修复 4. 注意 1.起因 这个问题要从今天刚遇到的事儿说起,昨晚代码出了个乌龙事件,本来正在dev分支进行新功能的开发,但是测试出现的问题是在release 分支 ...
- SQL server中自定义排序
select * from OrderPolicyDetail order by ( case Project when 'C' then 1, when 'A' then 2, when 'D' t ...
- 9、zabbix监控
9.1.监控: 1.初级(凡人): (1)识别监控的对象: (2)理解监控的对象: (3)细分监控对象的指标: (4)确定告警的基准线: 2.预中级(飞仙): (1)工具化和监控分离: (2)监控对象 ...
- Linux云计算-04_Linux用户及权限管理
Linux是一个多用户的操作系统,引入用户,可以更加方便管理Linux服务器,系统默认需要以一个用户的身份登录,而且在系统上启动进程也需要以一个用户身份器运行,用户可以限制某些进程对特定资源的权限控制 ...
- POJ 3984 迷宫(BFS)
入门BFS,第一次做,部分借鉴了大牛的 #include <iostream> #include <cstdio> #include <queue> using n ...
- 架构之:serverless架构
目录 简介 什么是serverless serverless的例子 简单的三层服务 消息驱动 FaaS FaaS的缺点 FaaS的优点 总结 简介 不知道什么时候,出现了一个叫做Serverless架 ...





