依据 Dioxus 0.7 optimizing 指南做两项改进: - 为数据驱动列表渲染补全显式 key(13 处,9 个文件): home/archives/tags/search 文章与标签列表、post_card/post_footer 标签、header 桌面/移动导航、admin dashboard/posts/write 列表。 使用各类型稳定唯一字段(post.id / tag / tag.name / item.label / err.id / year_group.year / month_group.month_en)作为 key, 让 Dioxus diff 正确识别元素身份。骨架屏 for _ in 0..N 静态占位 循环与已带 key 的评论树/admin 行不动。 - [profile.release] 加 panic = "abort":WASM 去掉 unwind 元数据减小 体积;server 端错误处理走 Result+?(见 error.rs),不依赖 panic unwind,无副作用。 其余文件为本机格式化(单行折叠/多行展开),一并提交。 验证:dx check 通过、cargo test 405 passed。
68 lines
2.3 KiB
Rust
68 lines
2.3 KiB
Rust
//! 前台布局组件
|
||
//!
|
||
//! 包裹所有前台路由,提供统一的 Header、Footer 与主内容区容器,
|
||
//! 并为不同路由在 SuspenseBoundary 中展示对应的骨架屏。
|
||
|
||
use dioxus::prelude::*;
|
||
|
||
use crate::components::footer::Footer;
|
||
use crate::components::header::Header;
|
||
use crate::components::nav::use_nav_items;
|
||
use crate::components::skeletons::archive_skeleton::ArchiveSkeleton;
|
||
use crate::components::skeletons::delayed_skeleton::DelayedSkeleton;
|
||
use crate::components::skeletons::home_skeleton::HomeSkeleton;
|
||
use crate::components::skeletons::post_detail_skeleton::PostDetailSkeleton;
|
||
use crate::components::skeletons::search_skeleton::SearchSkeleton;
|
||
use crate::components::skeletons::tags_skeleton::TagsSkeleton;
|
||
use crate::router::Route;
|
||
use crate::theme::ThemeToggle;
|
||
|
||
/// 根据当前前台路由选择对应的骨架屏组件。
|
||
fn route_skeleton(route: &Route) -> Element {
|
||
match route {
|
||
Route::Archives {} => rsx! {
|
||
DelayedSkeleton { ArchiveSkeleton {} }
|
||
},
|
||
Route::Tags {} | Route::TagDetail { .. } => rsx! {
|
||
DelayedSkeleton { TagsSkeleton {} }
|
||
},
|
||
Route::Search {} => rsx! {
|
||
DelayedSkeleton { SearchSkeleton {} }
|
||
},
|
||
Route::PostDetail { .. } => rsx! {
|
||
DelayedSkeleton { PostDetailSkeleton {} }
|
||
},
|
||
Route::NotFound { .. } => rsx! {
|
||
div { class: "py-20 md:py-28" }
|
||
},
|
||
_ => rsx! {
|
||
DelayedSkeleton { HomeSkeleton {} }
|
||
},
|
||
}
|
||
}
|
||
|
||
/// 前台整体布局组件。
|
||
///
|
||
/// 负责渲染 Header(含前台导航与主题切换)、主内容区与 Footer,
|
||
/// 并在路由内容加载过程中显示与路由匹配的骨架屏。
|
||
#[component]
|
||
pub fn FrontendLayout() -> Element {
|
||
let route = use_route::<Route>();
|
||
let nav_items = use_nav_items(route.clone());
|
||
|
||
rsx! {
|
||
div { class: "min-h-screen flex flex-col bg-paper-theme",
|
||
Header {
|
||
nav_items,
|
||
right_content: rsx! {
|
||
ThemeToggle {}
|
||
},
|
||
}
|
||
main { class: "flex-1 w-full max-w-3xl mx-auto px-6 py-6",
|
||
SuspenseBoundary { fallback: move |_| route_skeleton(&route), Outlet::<Route> {} }
|
||
}
|
||
Footer {}
|
||
}
|
||
}
|
||
}
|