Yew框架点击Route Link时如何添加.is-active导航CSS类
Yew + Bulma 导航栏激活样式实现方案
不需要拦截Link组件的点击事件,这种实现方式覆盖场景不全,维护成本高。yew-router 内置了获取当前激活路由的Hook,直接基于当前路由判断是否给导航项添加is-active类即可,能自动适配所有路由跳转场景:点击链接、浏览器前进/后退、地址栏直接输入、代码主动触发路由跳转都能正确显示激活状态。
实现步骤
- 在组件内调用
use_route::<AppRoutes>()获取当前匹配的路由,路由发生变化时组件会自动重渲染,不需要手动监听事件 - 将原代码中控制移动端汉堡菜单、折叠菜单展开状态的
active_class重命名(比如改为mobile_menu_active_class),避免和导航项激活类的变量名冲突 - 每个导航
Link的classes属性中增加判断逻辑:当前路由和Link指向的路由一致时,追加is-active样式类
修改后的完整代码
use yew::prelude::*; use yew_router::prelude::*; use crate::routes::app_routes::AppRoutes; #[function_component] pub fn Nav() -> Html { let navbar_menu_open = use_state_eq(|| false); // 获取当前激活的路由,路由变化时自动触发组件重渲染 let current_route = use_route::<AppRoutes>(); let toggle_navbar = { let navbar_menu_open = navbar_menu_open.clone(); Callback::from(move |_| { navbar_menu_open.set(!*navbar_menu_open); }) }; // 移动端汉堡菜单/折叠菜单的激活类 let mobile_menu_active_class = if *navbar_menu_open { "is-active" } else { "" }; html! { <nav class="navbar is-primary" role="navigation" aria-label="main navigation"> <div class="navbar-brand"> <h1 class="navbar-item is-size-3">{ "UVW" }</h1> <button class={classes!("navbar-burger", "burger", mobile_menu_active_class)} aria-label="menu" aria-expanded="false" onclick={toggle_navbar} > <span aria-hidden="true"></span> <span aria-hidden="true"></span> <span aria-hidden="true"></span> </button> </div> <div class={classes!("navbar-menu", mobile_menu_active_class)}> <div class="navbar-start"> <Link<AppRoutes> classes={classes!( "navbar-item", // 当前路由匹配Home时追加is-active类 (current_route == Some(AppRoutes::Home)).then_some("is-active") )} to={AppRoutes::Home} > { "Home" } </Link<AppRoutes>> <Link<AppRoutes> classes={classes!( "navbar-item", (current_route == Some(AppRoutes::About)).then_some("is-active") )} to={AppRoutes::About} > { "About" } </Link<AppRoutes>> <div class="navbar-item has-dropdown is-hoverable"> <div class="navbar-link"> { "More" } </div> <div class="navbar-dropdown"> <Link<AppRoutes> classes={classes!( "navbar-item", (current_route == Some(AppRoutes::Home)).then_some("is-active") )} to={AppRoutes::Home} > { "DropDown1" } </Link<AppRoutes>> <Link<AppRoutes> classes={classes!( "navbar-item", // 替换为对应下拉项实际指向的路由即可 (current_route == Some(AppRoutes::Home)).then_some("is-active") )} to={AppRoutes::Home} > { "DropDown2" } </Link<AppRoutes>> <Link<AppRoutes> classes={classes!( "navbar-item", (current_route == Some(AppRoutes::Home)).then_some("is-active") )} to={AppRoutes::Home} > { "DropDown3" } </Link<AppRoutes>> </div> </div> </div> </div> </nav> } }
注:代码中顺便修正了原实现里移动端菜单的逻辑错误:原代码激活类判断条件写反,会导致页面首次加载时汉堡按钮默认为激活状态、移动端菜单默认展开。
如果编译报错提示AppRoutes未实现PartialEq,在路由枚举的派生宏中补充该trait即可,示例:
#[derive(Debug, Clone, PartialEq, Routable)] pub enum AppRoutes { #[at("/")] Home, #[at("/about")] About, // 其余业务路由定义 }
内容的提问来源于stack exchange,提问作者tempbottle
相关产品推荐
相关产品推荐

