Vue中如何设计多级菜单才显得专业?
时间:2023-03-13 14:48:26
科技观察
是陈词滥调!我们虽然是Java猿,但是前端代码写起来一点都不含糊!今天想和大家聊一聊前端动态菜单,如何设计才显得专业!下面就以我们的天津项目为例,一起来看看吧。先截图看看效果:那么这样的菜单是怎么设计的呢?今天不想和大家过多谈论技术细节。我就说说路由是怎么设计的吧??。一旦您了解了路由的设计方式,剩下的问题就很简单了。1、路由设计有朋友做过vhr,知道如何在vhr中实现动态菜单。宋歌和大家一样,也在不断学习,不断提升的过程中。今天想和大家一起探讨一下TienChin项目中动态菜单的实现方案。看看有没有更好的解决办法。1.1菜单设计首先和小伙伴们一起回顾一下vhr的解决方案:在vhr中,权限的控制只控制在二级菜单,即一级菜单与权限无关。比如现在有一个一级菜单A和一个二级菜单B,B是A中的菜单。现在假设如果当前用户权限可以查看B菜单,那么A菜单会自动显示.如果当前用户权限不能查看B菜单,并且A菜单中没有其他子菜单可以显示,那么A菜单将不会显示。也就是说,A菜单是否显示,主要取决于其中是否有子菜单需要显示。如果有则显示A菜单,如果没有则不显示A菜单。vhr中的思路是这样的。在TienChin的项目中,这方面有一些变化:如果A中只有一个B,那么好像不用做两级菜单,直接显示B就可以了?用户操作也方便!这是第一个区别。1.2路由数据基于第一点,涉及到一个问题,即路由接口如何设计?最重要的是接口返回的数据格式应该是什么样的?首先小伙伴们应该知道,这里的路由是嵌套路由,即二级菜单嵌套在一级菜单中。即使这个地方展示的时候没有层级关系,比如上图中的促销活动,底层的数据结构也应该是嵌套的路由。好吧,我们不卖把戏,让我们看一个路由JSON:[{"name":"Monitor","path":"/monitor","hidden":false,"redirect":"noRedirect","component":"Layout","alwaysShow":true,"meta":{"title":"SystemMonitor","icon":"monitor","noCache":false,"link":null},"children":[{"name":"Online","path":"online","hidden":false,"component":"monitor/online/index","meta":{"title":"OnlineUser","icon":"online","noCache":false,"link":null}},{"name":"Job","path":"job","hidden":false,"component":"monitor/job/index","meta":{"title":"ScheduledTask","icon":"job","noCache":false,"link":null}}]},{"path":"/","hidden":false,"component":"Layout","children":[{"name":"Role","path":"role","hidden":false,"component":"system/role/index","meta":{"title":"RoleManagement","icon":"peoples","noCache":false,"link":null}}]}]这里我有列出两个菜单的例子,这两个例子比较有代表性,最终展示这个菜单的效果大致如下:接下来,在这里说说一些典型的属性:redirect:noRedirect表示路由在面包屑导航中不能被点击。alwaysShow:如果该属性设置为false,那么当当前菜单只有一个子菜单时,默认只显示子菜单,而忽略父菜单(如1.1节所述),但如果设置了该属性为true,无论当前菜单有多少个子菜单,都会显示当前菜单(这个和vhr中的效果类似)。每个父菜单都有自己的路径,每个子菜单也有自己的路径。父菜单的路径加上每个子菜单的路径构成了每个子菜单的路径。我们来看第二个角色管理菜单项。由于其父菜单中只有一个子菜单项,而父菜单中没有alwaysShow属性,所以最终显示该菜单项时,只显示里面的角色管理。不会显示父菜单(正好生成的JSON中没有提到父菜单的名称、图标等属性)。当然,这并不意味着你的JSON会自动以这种方式显示。JSON中的内容只是一个标记。最终如何显示取决于渲染:noShowingChildren)&&!item.alwaysShow">
还有一个功能我没有列出来。反正我们看名字就大概知道每个函数的意思了。可以看到这个div其实分为两部分。上面的模板是专门用来处理只有一个孩子的。Item情况(角色管理),具体处理方法是显示子项,忽略其他。在具体执行时,可能不会只有一个孩子,也可能根本就没有孩子。在这种情况下,可以直接显示父级(参见第1.3节)。下面的el-submenu处理有多个孩子的情况(系统监控)。另外,这里涉及到一个resolvePath,也是一个特别关键的方法。让我们粗略地看一下:resolvePath(routePath,routeQuery){if(isExternal(routePath)){returnroutePath}if(isExternal(this.basePath)){returnthis.basePath}if(routeQuery){letquery=JSON.parse(路由查询);return{path:path.resolve(this.basePath,routePath),query:query}}returnpath.resolve(this.basePath,routePath)}该函数主要作用是处理菜单的路径问题。我们来看看具体的判断逻辑:如果菜单的路径是外部链接(判断逻辑是检查路径是否有http或者https等前缀),即如果isExternal返回true,则路径将原封不动地退回。如果该菜单的父菜单路径为外部链接,则原样返回父菜单路径。如果有查询参数,则添加它们。最后通过path.resolve对路径进行简单的操作。可能有些朋友对path.resolve不熟悉。简单说一下:path.resolve()方法可以将多条路径解析为规范化的绝对??路径。它的处理方式类似于对这些路径一条一条进行cd操作。但是与cd操作不同的是,这些路径可以是文件,不需要实际存在(resolve()方法不使用底层文件系统判断路径是否存在,只是进行路径字符串操作)。例如:path.resolve('foo/bar','/tmp/file/','..','a/../subfile')等同于:cdfoo/barcd/tmp/file/cd。.cda/../subfilepwd举个简单的例子:path.resolve('/foo/bar','./baz')//输出是'/foo/bar/baz'path.resolve('/foo/bar','/tmp/file/')//输出为'/tmp/file'path.resolve('wwwroot','static_files/png/','../gif/image.gif')//当前工作路径为/home/javaboy/node,输出结果为'/home/javaboy/node/wwwroot/static_files/gif/image.gif'现在大家知道菜单跳转路径是怎么来的了吧!1.3外链问题在TienChin项目中,菜单中还存在外链问题。该外部链接有两种不同的展示思路:点击外部链接直接打开新标签页,在新标签页中显示新页面。点击外部链接可以在当前项目中打开一个新的标签页,标签页中会显示新的内容。对于第一种情况,我就不给大家演示了。对于第二种情况,我截图给大家看一下:就是在当前项目的tab中显示一个外部链接的内容。我们先来看第一种情况。即点击菜单后,网页将在新标签页中打开。这个菜单的JSON格式如下:{"name":"http://www.javaboy.org","path":"http://www.javaboy.org","hidden":false,"component":"Layout","meta":{"title":"天津健身官网","icon":"guide","noCache":false,"link":"http://www.javaboy.org"}}你看,没有children,因为不需要,显示这个的时候,只当一个children,而且menuitem的路径是http路径,点击后自然跳转到新标签页。对于第二种情况,点击外部链接会在当前项目中打开一个新的标签页,标签页中会显示链接的内容。它的JSON结构类似如下:{"name":"http://www.javaboy.org","path":"/","hidden":false,"component":"Layout","meta":{"title":"天津健身官网","icon":"guide","noCache":false,"link":null},"children":[{"name":"www.javaboy.org","path":"www.javaboy.org","hidden":false,"component":"InnerLink","meta":{"title":"天津健身官网","icon":"guide","noCache":false,"link":"http://www.javaboy.org"}}]}这个其实没什么好说的。和上面系统监控的情况类似,但是只有一个子菜单。呈现菜单时,只呈现一个子菜单。由于父子菜单的路径不是以http或https等地址开头,所以这个链接最终生成的路径是/www.javaboy.org,然后这个路径的内容就会显示在InnerLink组件上,最后就是上图看到的效果了。