Grails布局中设置激活导航标签的最优实现方案问询
Grails布局中实现导航标签高亮的最优方案
一、你提出的写法完全没问题
在Grails的main.gsp这类布局文件里,直接写${ controller == 'controller1' ? 'active' : '' }这种判断逻辑是完全可行的。Grails会自动把当前请求的控制器名称暴露成GSP能直接访问的controller变量,所以这个判断能精准触发,给对应导航项加上active类。
修改后的代码示例:
<ul class="nav nav-pills"> <li class="nav-item"> <g:link controller="controller1" class="nav-link ${ controller == 'controller1' ? 'active' : '' }">Controller 1</g:link> </li> <li class="nav-item"> <g:link controller="controller2" class="nav-link ${ controller == 'controller2' ? 'active' : '' }">Controller 2</g:link> </li> </ul>
这种方式好处是简单直接,不用额外配置,适合导航项少的场景;但导航多了之后,重复的判断代码会显得冗余。
二、更优雅的实现方案
如果导航项多,或者需要更灵活的判断逻辑,推荐下面两种方式:
1. 自定义TagLib封装激活逻辑
把导航激活的判断逻辑封装成自定义TagLib,避免重复写判断代码:
// grails-app/taglib/com/example/NavTagLib.groovy package com.example class NavTagLib { static namespace = 'nav' def activeLink = { attrs, body -> def targetController = attrs.controller def cssClass = 'nav-link' // 判断当前控制器是否匹配目标控制器 if (controller == targetController) { cssClass += ' active' } // 支持传入额外的class属性 if (attrs.class) { cssClass += " ${attrs.class}" } // 生成g:link标签 out << g.link(controller: targetController, class: cssClass, body()) } }
之后在main.gsp里直接用这个自定义标签就行:
<ul class="nav nav-pills"> <li class="nav-item"> <nav:activeLink controller="controller1">Controller 1</nav:activeLink> </li> <li class="nav-item"> <nav:activeLink controller="controller2">Controller 2</nav:activeLink> </li> </ul>
这种方式的优势是逻辑统一复用,后续要改激活规则,只需要修改TagLib,不用逐个改导航项。
2. 循环渲染导航项(适合大量导航)
如果导航项很多,可以把导航数据做成一个列表,循环渲染,减少重复代码:
在main.gsp里:
<% // 定义导航数据列表 def navItems = [ [controller: 'controller1', label: 'Controller 1'], [controller: 'controller2', label: 'Controller 2'] ] %> <ul class="nav nav-pills"> <g:each in="${navItems}" var="item"> <li class="nav-item"> <g:link controller="${item.controller}" class="nav-link ${ controller == item.controller ? 'active' : '' }"> ${item.label} </g:link> </li> </g:each> </ul>
这样新增导航项的时候,只需要在navItems里加一行数据就行,不用重复写<li>和<g:link>标签,维护起来更方便。
三、扩展场景:支持动作级高亮
如果需要针对某个控制器下的特定动作高亮导航,可以结合action变量扩展判断:
<g:link controller="controller1" class="nav-link ${ controller == 'controller1' && action == 'index' ? 'active' : '' }"> Controller 1 首页 </g:link>
也可以在自定义TagLib里加上action参数,让判断更灵活:
def activeLink = { attrs, body -> def targetController = attrs.controller def targetAction = attrs.action def cssClass = 'nav-link' boolean isActive = false // 先判断控制器是否匹配 if (targetController == controller) { // 如果没指定动作,或者动作也匹配,就激活 if (!targetAction || targetAction == action) { isActive = true } } if (isActive) { cssClass += ' active' } if (attrs.class) { cssClass += " ${attrs.class}" } out << g.link(controller: targetController, action: targetAction, class: cssClass, body()) }
使用时可以指定动作:
<nav:activeLink controller="controller1" action="index">Controller 1 首页</nav:activeLink>
内容的提问来源于stack exchange,提问作者Bioman
相关产品推荐
相关产品推荐

