--- title: '教學' slug: /tutorial --- ## 介紹 在這個實作教程中,我們將學習如何使用 Yew 建立 Web 應用程式。 **Yew** 是一個現代的 [Rust](https://www.rust-lang.org/) 框架,用於使用 [WebAssembly](https://webassembly.org/) 建立前端 Web 應用程式。 Yew 透過利用 Rust 強大的類型系統,鼓勵可重複使用、可維護和良好結構化的架構。 一個龐大的社群所創造的函式庫生態系統,稱為Rust 中的[crates](https://doc.rust-lang.org/book/ch07-01-packages-and-crates.html),為常用模式(如狀態管理)提供了元件。 Rust 的套件管理器 [Cargo](https://doc.rust-lang.org/cargo/) 允許我們利用 [crates.io](https://crates.io) 上提供的大量 crate,例如 Yew。 ### 我們將要建構的內容 Rustconf 是 Rust 社群每年舉辦的星際派對。 Rustconf 2020 有大量的演講,提供了大量的資訊。 在這個實作教程中,我們將建立一個 Web 應用程序,幫助其他 Rustaceans 了解這些演講並從一個頁面觀看它們。 ## 設定 ### 先決條件 這個教程假設您已經熟悉 Rust。如果您是Rust 的新手,免費的[Rust 書](https://doc.rust-lang.org/book/ch00-00-introduction.html) 為初學者提供了一個很好的起點,並且即使對於有經驗的Rust 開發人員來說,它仍然是一個很好的資源。 確保安裝了最新版本的 Rust,方法是執行 `rustup update` 或[安裝 Rust](https://www.rust-lang.org/tools/install)。 安裝 Rust 後,您可以使用 Cargo 執行以下命令安裝 `trunk`: ```bash cargo install trunk ``` 我們還需要新增 WASM 建置目標,執行以下命令: ```bash rustup target add wasm32-unknown-unknown ``` ### 設定項目 首先,建立一個新的 cargo 專案: ```bash cargo new yew-app cd yew-app ``` 為了驗證 Rust 環境是否設定正確,使用 cargo 建置工具執行初始專案。 在關於建置過程的輸出之後,您應該會看到預期的 "Hello, world!" 訊息。 ```bash cargo run ``` ## 我們的第一個靜態頁面 為了將這個簡單的命令列應用程式轉換為一個基本的 Yew web 應用程序,需要進行一些更改。 ```toml title="Cargo.toml" {7} [package] name = "yew-app" version = "0.1.0" edition = "2021" [dependencies] yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] } ``` :::info 如果你只是正在建立一個應用程序,你只需要 `csr` 特性。它將啟用 `Renderer` 和所有與客戶端渲染相關的程式碼。 如果你正在製作一個函式庫,請不要啟用此特性,因為它會將客戶端渲染邏輯拉入伺服器端渲染包中。 如果你需要 Renderer 進行測試或範例,你應該在 `dev-dependencies` 中啟用它。 ::: ```rust ,no_run title="src/main.rs" use yew::prelude::*; #[function_component(App)] fn app() -> Html { html! {

{ "Hello World" }

} } fn main() { yew::Renderer::::new().render(); } ``` 現在,讓我們在專案的根目錄中建立一個 `index.html`。 ```html title="index.html" ``` ### 啟動開發伺服器 運行以下命令建置並在本地提供應用程式。 ```bash trunk serve --open ``` :::info 刪除選項 '--open' 以在執行 `trunk serve` 後不開啟預設瀏覽器。 ::: Trunk 將在您修改任何原始程式碼檔案時即時重新建立您的應用程式。 預設情況下,伺服器將在位址 '127.0.0.1' 的連接埠 '8080' 上監聽 => [http://localhost:8080](http://127.0.0.1:8080)。 若要變更這部分配置,請建立以下檔案並根據需要進行編輯: ```toml title="Trunk.toml" [serve] # 區域網路上的監聽位址 address = "127.0.0.1" # 廣域網路上的監聽位址 # address = "0.0.0.0" # 監聽的端口 port = 8000 ``` 如果您有興趣,您可以執行 `trunk help` 和 `trunk help ` 以獲取更多關於正在進行的流程的詳細資訊。 ### 恭喜 您現在已經成功設定了 Yew 開發環境,並建立了您的第一個 Yew Web 應用程式。 ## 建立 HTML Yew 利用了 Rust 的過程宏,並為我們提供了一種類似於 JSX(JavaScript 的擴展,可讓您在 JavaScript 中編寫類似 HTML 的程式碼)的語法來建立標記。 ### 轉換為經典 HTML 由於我們已經對我們的網站長什麼樣子有了一個很好的想法,我們可以簡單地將我們的草稿轉換為與 `html!` 相容的表示。如果您習慣於編寫簡單的 HTML,那麼您在 `html!` 中編寫標記時應該沒有問題。要注意的是,這個巨集與 HTML 有一些不同之處: 1. 表達式必須用大括號(`{ }`)括起來 2. 只能有一個根節點。如果您想要在不將它們包裝在容器中的情況下擁有多個元素,可以使用空標籤/片段(`<> ... `) 3. 元素必須正確關閉。 我們想要建立一個佈局,原始 HTML 如下: ```html

RustConf Explorer

Videos to watch

John Doe: Building and breaking things

Jane Smith: The development process

Matt Miller: The Web 7.0

Tom Jerry: Mouseless development

John Doe: Building and breaking things

video thumbnail
``` 現在,讓我們將這個 HTML 轉換為 `html!`。將下列程式碼片段輸入(或複製/貼上)到 `app` 函數的主體中,以便函數傳回 `html!` 的值 ```rust ,ignore html! { <>

{ "RustConf Explorer" }

{"Videos to watch"}

{ "John Doe: Building and breaking things" }

{ "Jane Smith: The development process" }

{ "Matt Miller: The Web 7.0" }

{ "Tom Jerry: Mouseless development" }

{ "John Doe: Building and breaking things" }

video thumbnail
} ``` 刷新瀏覽器頁面,您應該看到以下輸出: ![Running WASM application screenshot](/img/tutorial_application_screenshot.png) ### 在標記中使用 Rust 語言結構 在 Rust 中編寫標記的一個很大的優勢是,我們在標記中獲得了 Rust 的所有優點。 現在,我們不再在 HTML 中硬編碼影片列表,而是將它們定義為 `Vec` 的 `Video` 結構體。 我們建立一個簡單的 `struct`(在 `main.rs` 或我們選擇的任何檔案中)來保存我們的資料。 ```rust struct Video { id: usize, title: String, speaker: String, url: String, } ``` 接下來,我們將在 `app` 函數中建立這個結構體的實例,並使用它們來取代硬編碼的資料: ```rust use website_test::tutorial::Video; // 換成你自己的路徑 let videos = vec![ Video { id: 1, title: "Building and breaking things".to_string(), speaker: "John Doe".to_string(), url: "https://youtu.be/PsaFVLr8t4E".to_string(), }, Video { id: 2, title: "The development process".to_string(), speaker: "Jane Smith".to_string(), url: "https://youtu.be/PsaFVLr8t4E".to_string(), }, Video { id: 3, title: "The Web 7.0".to_string(), speaker: "Matt Miller".to_string(), url: "https://youtu.be/PsaFVLr8t4E".to_string(), }, Video { id: 4, title: "Mouseless development".to_string(), speaker: "Tom Jerry".to_string(), url: "https://youtu.be/PsaFVLr8t4E".to_string(), }, ]; ``` 為了顯示它們,我們需要將 `Vec` 轉換為 `Html`。我們可以透過建立一個迭代器,將其映射到 `html!` 並將其收集為 `Html` 來實現: ```rust ,ignore let videos = videos.iter().map(|video| html! {

{format!("{}: {}", video.speaker, video.title)}

}).collect::(); ``` :::tip 在清單項目上使用鍵有助於 Yew 追蹤清單中哪些項目發生了變化,從而實現更快的重新渲染。 [始終建議在清單中使用鍵](/concepts/html/lists.mdx#keyed-lists)。 ::: 最後,我們需要用從資料建立的 `Html` 取代硬編碼的影片清單: ```rust ,ignore {6-10} html! { <>

{ "RustConf Explorer" }

{ "Videos to watch" }

-

{ "John Doe: Building and breaking things" }

-

{ "Jane Smith: The development process" }

-

{ "Matt Miller: The Web 7.0" }

-

{ "Tom Jerry: Mouseless development" }

+ { videos }
// ... } ``` ## 元件 組件是 Yew 應用程式的構建塊。透過組合組件(可以由其他組件組成),我們建立我們的應用程式。透過為可重複使用性建立元件並保持它們的通用性,我們將能夠在應用程式的多個部分中使用它們,而無需重複程式碼或邏輯。 到目前為止我們一直在使用的 `app` 函數是一個元件,稱為 `App`。它是一個「函數式元件」。 1. 結構體組件 2. 函數式組件 在本教程中,我們將使用函數式元件。 現在,讓我們將 `App` 元件拆分為更小的元件。我們首先將影片清單提取到自己的組件中。 ```rust ,compile_fail use yew::prelude::*; struct Video { id: usize, title: String, speaker: String, url: String, } #[derive(Properties, PartialEq)] struct VideosListProps { videos: Vec