猿问

Jquery 自动导航高亮的相关问题,求大神指教.

想用JS直接实现系统菜单的导航高亮功能,其实就是自动检测页面url找到对应的元素addClass;不过因为本人菜鸟,实在写不出,求大神指教。

HTML结构如下(注释中就是基本需求)

如上代码中的注释,我写了一个,已经基本满足上面的要求,但是还有一个需求,就是某些页面的url不在菜单里,也要让某个菜单高亮。比如上面的用户管理=admin/user/index ,进入用户管理肯定没问题,但是我还有一个 添加用户admin/user/add,进入添加用户这个页面的时候也想让 用户管理 href=admin/user/index这个菜单高亮,就不知道怎么写了。

我的想法是,访问页面的时候如果url存在在菜单中就自动高亮,如果不存在,如刚才说的添加用户admin/user/add,定义一个函数 如 set_nav_active(url) ,然后在admin/user/add这个页面 传入他想要高亮的菜单url ,比如se_nav_active(admin/user/index),但是,想法是有了,不知道怎么写了,求大神指教,或者大神有没有更好的办法


开心每一天1111
浏览 639回答 1
1回答

富国沪深

这个问题很有意思,总结一下,你要解决的问题有两个根据当前 URL 找到匹配的&nbsp;href&nbsp;属性找到对应第 1 找到的&nbsp;href&nbsp;属性的那个&nbsp;<a>,对它以及它的几级父元素添加状态下面来一个一个的解决示例都是用的 es6 语法,不懂的话可以自己去 babel-try it out,或者 typescript playgournd 转换成 es5 的。找到匹配的 href首先,得让&nbsp;href&nbsp;和当前地址处于同样的目录级别表示。比如 href 里是&nbsp;admin/....,那当前页面地址&nbsp;window.location.pathname&nbsp;也要处理成这样,比如当前地址可能是&nbsp;/admin/...&nbsp;,要去掉第一个&nbsp;/;或者当前地址是&nbsp;/appname/admin/....,要去掉前面的&nbsp;/appname/。的过来,处理每个&nbsp;href&nbsp;去适配当前地址的表示也是一样的(其实这样更合理,只是处理起来更麻烦)const&nbsp;root&nbsp;=&nbsp;"/appname/";const&nbsp;menuUrls&nbsp;=&nbsp;$(".sidebar-menu&nbsp;a").map(function()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;`${root}${$(this).attr("href")}`; });这会得到包含所有链接的&nbsp;href&nbsp;属性的一个数组(jQuery 对象),我们可以遍历这个数组来寻找匹配的 URL,不过找到 URL 之后再去找对应的&nbsp;<a>&nbsp;是件麻烦事,所以,其实应该生成一个 map(JS 对象)const&nbsp;urlsMap&nbsp;=&nbsp;$(".sidebar-menu&nbsp;a") &nbsp;&nbsp;&nbsp;&nbsp;.toArray() &nbsp;&nbsp;&nbsp;&nbsp;.reduce((map,&nbsp;a)&nbsp;=>&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;$a&nbsp;=&nbsp;$(a);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;url&nbsp;=&nbsp;`${root}${$a.attr("href")}`; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map[url]&nbsp;=&nbsp;$a;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;map; &nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;{});现在会得到一个&nbsp;urlsMap,它是键是 URL,就是根据&nbsp;href&nbsp;处理而来的 URL。值是一个被 jQuery 封装的&nbsp;<a>&nbsp;的 DOM 对象,一一对应的关系。第一轮,精确匹配let&nbsp;pathname&nbsp;=&nbsp;window.location.pathname;let&nbsp;foundUrl&nbsp;=&nbsp;Object.keys(urlsMap) &nbsp;&nbsp;&nbsp;&nbsp;.fitler(url&nbsp;=>&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;url&nbsp;===&nbsp;pathname; &nbsp;&nbsp;&nbsp;&nbsp;})[0];如果&nbsp;foundUrl&nbsp;是一个字符串,说明找到了,不然就是没找到(因为 filter 的结果是个空数组,所以它的第 0 个元素是 undefined)。如果没找到,再进行第二轮,这时候需要截掉&nbsp;pathname&nbsp;的最后一部分,这也是&nbsp;pathname&nbsp;和&nbsp;foundUrl&nbsp;用&nbsp;let&nbsp;申明而不用&nbsp;const&nbsp;申明的原因第二轮,startsWith 匹配if&nbsp;(!foundUrl)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;去掉最后一个&nbsp;/&nbsp;及其后的部分 &nbsp;&nbsp;&nbsp;&nbsp;pathname&nbsp;=&nbsp;pathname.replace(/\/[^\/]+$/,&nbsp;""); &nbsp;&nbsp;&nbsp;&nbsp;foundUrl&nbsp;=&nbsp;Object.keys(urlsMap) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.filter(url&nbsp;=>&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;url.startsWith(pathnem); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;})[0]; }如果这样还没找到,你还需要再往前找,你可以考虑用一个循环代替上面的&nbsp;if&nbsp;分支,注意循环的结束条件,不要搞成死循环了。最终也没找到,那就拉倒吧。如果找到了,那么&nbsp;foundUrl&nbsp;对应的那个&nbsp;<a>&nbsp;就是要高亮的。这个&nbsp;<a>&nbsp;很好找,因为我们建了映射表const&nbsp;$a&nbsp;=&nbsp;urlsMap[foundUrl];下面进行第二步改变相关元素的状态这时候就需要找三个东西,<a>&nbsp;外层的&nbsp;<li>,再外层的&nbsp;.treeview-menu&nbsp;和再外层的&nbsp;.treeview。如果都是直接父级关系,那很好找,依次取&nbsp;.parent()&nbsp;就好。如果不是,那就用&nbsp;.closest(),下面的代码假设是这种情况$li&nbsp;=&nbsp;$a.closest("li"); $treeViewMenu&nbsp;=&nbsp;$li.closest(".treeview-menu"); $treeView&nbsp;=&nbsp;$treeViewMenu.closest(".treeview");都找到了,改个类就容易了(因为 jQuery 的容错性,完全不需要去判断找没找到,直接改就是了)$li.addClass("active"); $treeViewMenu.addClass("menu_open"); $treeView.addClass("active");搞定是搞定了,但是上面的代码都是直接写的,没测试,所以自己小心着用。
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答