加导航、加收藏页!

之前咱们的“潮狗”App 只有一个页面:打开就是狗图,关了还是狗图。
今天,我们要给它加房间、加导航、加收藏夹,让它从“狗图放映机”升级成—— “狗迷之家”App

第一步:先搞个“户型图”——代码结构整理

现在项目小,代码全塞一个文件也行。但以后要加登录页、设置页、用户页……
总不能全挤在一个 main.rs 里吧?那不成了“狗窝叠狗窝”!

所以我们先来整理房间,像装修一样搞个“户型图”:

src/
├── main.rs           # 入口,像“大门”
├── backend.rs        # 后端逻辑,像“厨房”(做饭的地方)
└── components/       # 所有UI组件,像“客厅+卧室+书房”
    ├── mod.rs        # 组件的“总开关”
    ├── nav.rs        # 导航栏,像“玄关+门厅”
    ├── view.rs       # 主页面,像“客厅”
    └── favorites.rs  # 收藏页,像“书房”

好处:

  • 代码不乱跑
  • 找东西快
  • 将来还能“复制粘贴”到别的项目里用

第二步:装“智能门锁”——路由系统(Router)

你想去“书房”还是“厨房”?得靠“门牌号”来导航。

在网页世界里,URL 就是门牌号

  • / → 客厅(看狗图)
  • /favorites → 书房(看收藏)

Dioxus 提供了一个超智能的“路由系统”,它能根据你输入的网址,自动打开对应的房间。

安装路由系统

先在 Cargo.toml 里加个功能:

[dependencies]
dioxus = { version = "0.6.0", features = ["fullstack", "router"] }

加了 "router",就像给房子装了“智能门禁系统”。

第三步:贴“门牌号”——定义路由

main.rs,我们用一个 枚举(enum) 来定义所有房间:

#[derive(Routable, Clone, PartialEq)]
enum Route {
    #[route("/")]
    DogView,

    #[route("/favorites")]
    Favorites,
}

解释:

  • #[route("/")] → 根路径,就是“客厅”
  • #[route("/favorites")] → 收藏页,就是“书房”
  • 每个“门牌号”对应一个组件(比如 DogView

只要名字对得上,Dioxus 就知道该进哪个门!


第四步:换“大门”——用 Router 替换主页面

原来 main.rs 是这样:

fn app() -> Element {
    rsx! {
        DogView {}  // 直接显示狗图
    }
}

现在我们换成:

fn app() -> Element {
    rsx! {
        Router::<Route> {}  // 让“路由系统”来决定显示哪个页面
    }
}

就像把“固定门”换成“智能门禁”;你输入 /,它开“客厅”;你输入 /favorites,它开“书房”。


第五步:加“玄关”——导航栏(NavBar)

现在可以跳转了,但…… 用户怎么知道有“收藏页”?总不能让他们手动输网址吧?

所以我们加个导航栏(NavBar),就像房子的“玄关”,上面挂着“去客厅”、“去书房”的按钮。

创建 nav.rs
use crate::Route;
use dioxus::prelude::*;

#[component]
pub fn NavBar() -> Element {
    rsx! {
        div { id: "title",
            Link { to: Route::DogView, h1 { "🌭 HotDog!" } }
            Link { to: Route::Favorites, id: "heart", "♥️" }
        }
        Outlet::<Route> {}  // 当前页面会显示在这里!
    }
}

Link 是“智能链接”:

  • 点它,URL 变了,页面也自动切换
  • 类型安全,不会点到不存在的页面!

Outlet 是“电视墙”: 它会自动显示当前路由对应的页面(比如 DogViewFavorites)。

第六步:让“玄关”生效——加 #[layout]

现在 NavBar 写好了,但怎么让它一直显示
总不能每个页面都复制一遍吧?

Dioxus 提供了 #[layout] 属性,就像给“玄关”通电,让它包裹所有页面

#[derive(Routable, PartialEq, Clone)]
enum Route {
    #[layout(NavBar)]  //  所有下面的页面都会被 NavBar 包裹!
    #[route("/")]
    DogView,

    #[route("/favorites")]
    Favorites,
}

效果:
无论你去哪个页面,顶部的导航栏都稳稳在那,就像微信顶部的标题栏一样!

第七步:建“书房”——收藏页(Favorites)

终于到了激动人心的时刻:我们要做一个收藏页,把之前存进数据库的狗图,全部“捞”出来展示!

1. 先写个“取图”函数(后端)

backend.rs 里加一个 list_dogs 函数:

#[server]
pub async fn list_dogs() -> Result<Vec<(usize, String)>, ServerFnError> {
    let dogs = DB.with(|f| {
        f.prepare("SELECT id, url FROM dogs ORDER BY id DESC LIMIT 10")
            .unwrap()
            .query_map([], |row| Ok((row.get(0)?, row.get(1)?)))
            .unwrap()
            .map(|r| r.unwrap())
            .collect()
    });
    Ok(dogs)
}

意思是:
从数据库里,按“最新收藏”排序,取最近10张狗图。


2. 再写“书房”页面(前端)

favorites.rs 里:

use dioxus::prelude::*;

#[component]
pub fn Favorites() -> Element {
    // 用 use_resource 拿数据,.suspend()? 等它加载完
    let mut favorites = use_resource(crate::backend::list_dogs).suspend()?;

    rsx! {
        div { id: "favorites",
            div { id: "favorites-container",
                for (id, url) in favorites().unwrap() {
                    div {
                        key: id,  // 每条数据都要有唯一 key
                        class: "favorite-dog",
                        img { src: "{url}" }  // 显示狗图
                    }
                }
            }
        }
    }
}

关键点:

  • use_resource:异步加载数据
  • .suspend()?:等数据回来再渲染(避免白屏)
  • for 循环:把每张狗图都画出来

成果展示

现在你的 App 长这样:

[ 🌭 HotDog! ] [ ♥️ ]   ← 导航栏(全页面通用)
----------------------------
       🐶 狗图在这里        ← 当前页面内容
----------------------------
  • 点首页图标 → 看随机狗图
  • 点红心 → 进入“收藏夹”,看所有收藏的狗图!

三步建多页面 App

步骤 做什么 类比
1. 装路由 features = ["router"] 给房子装“智能门禁”
2. 贴门牌 enum Route { #[route("/")] DogView } 给每个房间贴标签
3. 加玄关 #[layout(NavBar)] + Outlet 所有页面共享导航栏

你已经用 Dioxus 做出了一个全功能的“潮狗”App

  • 有导航栏
  • 能异步加载狗图
  • 会调用后端函数
  • 还能存进数据库!

几分钟就搞出这么个“全能选手”,简直比楼下王阿姨包饺子还快!现在,是时候让它“走出实验室”,打包成真正的 App,发给朋友炫耀了!


第一步:跨平台测试——“潮狗”去哪都能跑!

之前我们只在浏览器里玩“潮狗”。但现在我们要让它:上手机! 上电脑! 上网页!

Dioxus 0.6 版本太给力了,一个命令 dx serve,就能让你的 App 在手机、电脑、网页上实时预览!


测试 iPhone 版(iOS)

想让“潮狗”跑在 iPhone 上?
你需要:

  1. 一台 Mac 电脑(苹果生态的“入场券”)
  2. 安装 Xcode(苹果官方“开发神器”)
  3. 装好 iOS 模拟器(相当于“虚拟iPhone”)
  4. 装上 Rust 的 iOS 编译工具链

小提示:
你不需要马上交“苹果税”(99美元年费),
只有当你想上传到 App Store 或真机测试时才需要。

启动模拟器:
# 打开模拟器
open /Applications/Xcode.app/Contents/Developer/Applications/Simulator.app

# 查看有哪些设备
xcrun simctl list

# 启动一台 iPhone 13 Pro
xcrun simctl boot "iPhone 13 Pro"

# 【注】:如果使用的是ios18.31版本运行不起来,当前的版本不支持,目前官方也没有明确的解决方案

然后运行:

dx serve --platform ios

成功!你的“潮狗”App 已经在“虚拟iPhone”上跑起来了!
完全不用改代码,丝滑得像德芙巧克力!

测试安卓版(Android)

安卓更复杂一点,但流程类似:

  1. Android StudioSDK/NDK
  2. 设置环境变量:JAVA_HOME, ANDROID_HOME
  3. 安卓模拟器(比如 Pixel 6)
  4. 装 Rust 的安卓编译工具链

【注】:本节没有实际验证,根据官网的文档来看应该问题不大。

启动模拟器:

emulator -avd Pixel_6_API_34 -netdelay none -netspeed full

然后运行:

dx serve --platform android

但!你可能会遇到一个报错:

“找不到 OpenSSL,编译失败!”

这是啥?简单说:Rust 的某个库在安卓上“水土不服”


解决安卓编译问题

别慌!我们有个“急救包”—— 让 Rust 自带 OpenSSL,而不是依赖安卓系统。

Cargo.toml 里加一段:

[target.'cfg(target_os = "android")'.dependencies]
openssl = { version = "0.10", features = ["vendored"] }

意思是:只有在编译安卓版时,才启用“自带OpenSSL”功能。

再运行 dx serve --platform android
这次——成功了!

你的“潮狗”App 现在也能在安卓手机上跑了!

小知识:
不是所有 Rust 库都完美支持手机。
移动端的 Rust 生态还在“青春期”,
遇到问题别怕,查文档、加配置,就能搞定!


测试电脑版(Desktop)

“潮狗”还能当电脑软件用!
支持 macOS、Windows、Linux!

运行:

dx serve --platform desktop

看!一个独立窗口弹出来,你的 App 现在是个“正经桌面软件”了!


在这里插入图片描述

第二步:打包——把“潮狗”装进“礼盒”!

测试完,该打包发布了!

Dioxus 提供了 dx bundle 命令,
就像一个“智能打包机”,能把你的 App 打包成各种格式,发给朋友!

打包网页版(Web)

运行:

dx bundle --platform web

它会生成一个 public 文件夹,里面是:

public/
├── index.html          # 主页
├── assets/             # 图标、CSS
└── wasm/               # 核心代码(.wasm 文件)

还有一个 server 文件,用来处理后端请求。

部署时:

  • public 文件夹扔到任何静态服务器(比如 Vercel、Netlify)
  • 同时运行 server 程序,处理数据库请求

如果用 Docker,记得加 IP=0.0.0.0,不然别人访问不了!


打包电脑版(Desktop)

想发给朋友当软件用?打包成 .dmg(Mac)或 .exe(Windows)!

dx bundle --platform desktop --package-types "dmg"

它会生成:

  • HotDog.app(Mac 应用)
  • HotDog_0.1.0_aarch64.dmg(可分发的安装包)

注意:
Mac 用户第一次打开可能会提示“不安全”,
需要右键“打开”绕过。
正式发布时,建议签名 + 公证(Notarize),让用户放心点。

打包手机版(Mobile)

# 打包 iOS
dx bundle --platform ios --package-types "ipa"

# 打包 Android
dx bundle --platform android --package-types "apk"

生成的 .ipa.apk 文件,
就可以发给朋友安装了!

注意:
上架 App Store 或 Google Play 前,
必须签名(Sign)你的 App。
Dioxus 目前不内置这个功能,
你可以参考 Tauri 的签名文档 来操作。


第三步:自定义你的“礼盒”外观!

想让你的 App 更专业?
可以自定义:

  • App 图标(icon)
  • 开发者名字(publisher)
  • 应用 ID(identifier,比如 com.yourname.hotdog

Dioxus.toml 里加配置:

[application]
name = "HotDog"

[bundle]
identifier = "com.john.hotdog"
publisher = "John's Dog Empire"
icon = ["assets/icon.png"]

图标建议提供多个尺寸,适配不同设备。


高级技巧:用 JSON 自动化打包!

Dioxus 0.6 还支持 --json-output 模式,
可以把打包结果输出成 JSON 格式
方便用脚本自动处理。

比如,你想用 CI/CD(比如 GitHub Actions)自动打包,
就可以这样提取打包路径:

dx bundle --platform desktop --json-output | tail -1 | jq -r '.json | fromjson | .BundleOutput.bundles[]'

输出:

/path/to/HotDog.app
/path/to/HotDog.dmg

这样就能让机器人自动上传、发版,
你只管写代码,发布交给机器!

总结:一键打包,全平台通吃!

平台 打包命令 输出格式
网页 dx bundle --platform web HTML + CSS + WASM
电脑 dx bundle --platform desktop .app, .dmg, .exe, .deb
iOS dx bundle --platform ios .ipa
安卓 dx bundle --platform android .apk

恭喜你,正式成为一名“全栈狗迷”!

你现在可以:

  1. .apk 发给安卓朋友
  2. .dmg 发给 Mac 朋友
  3. 把网页版部署到 Vercel,生成一个链接发朋友圈
  4. 在简历上写:“精通跨平台全栈开发”
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐