跳到主要內容
版本:0.21

屬性

注意事項

屬性通常簡稱為「Props」。

屬性基本上是可以由 Yew 持續監控的組件引數。

一種類型必須先實作 Properties 性狀,才可以使用為組件的屬性。

重新整理時,Yew 會在比對虛擬 DOM 時檢查 prop 是否已變更,以得知是否需要重新整理巢狀元件。基於此情況,Yew 可以被認為是一種反應非常快速的架構,因為父元件的變更會永遠向下傳播,而且這個檢視永遠不會與 prop/狀態所提供的資料不同步。

提示

如果您尚未完成教學課程,請嘗試自行測試這個反應能力!

派生巨集

Yew 提供一個派生巨集,可輕鬆在結構中實作 `Properties` 特徵。

類型派生 `Properties` 也必須實作 `PartialEq`,這樣 Yew 才能進行資料比較。

use yew::Properties;

#[derive(Properties, PartialEq)]
pub struct Props {
pub is_loading: bool,
}

用於函式元件

屬性 `#[function_component]` 允許在函式引數中選用接收 Props。若要提供 Props,它們會透過 `html!` 巨集中屬性指定。

use yew::{function_component, html, Html, Properties};

#[derive(Properties, PartialEq)]
pub struct Props {
pub is_loading: bool,
}

#[function_component]
fn HelloWorld(props: &Props) -> Html {
html! { <>{"Am I loading? - "}{props.is_loading.clone()}</> }
}

// Then supply the prop
#[function_component]
fn App() -> Html {
html! {<HelloWorld is_loading={true} />}
}

派生巨集欄位屬性

派生 `Properties` 時,預設所有欄位都是必要的。下列屬性允許您提供 Props 預設值,當父項未設定時會使用此預設值。

提示

屬性不會顯示在 Rustdoc 生成的文件中。您的屬性文件字串應說明 prop 是否為選用,以及是否具有特殊預設值。

使用 `Default` 特徵,以欄位類型的預設值初始化 prop 值。

use yew::{function_component, html, Html, Properties};

#[derive(Properties, PartialEq)]
pub struct Props {
#[prop_or_default]
pub is_loading: bool,
}

#[function_component]
fn HelloWorld(props: &Props) -> Html {
if props.is_loading.clone() {
html! { "Loading" }
} else {
html! { "Hello world" }
}
}

// Then use like this with default
#[function_component]
fn Case1() -> Html {
html! {<HelloWorld />}
}
// Or no override the default
#[function_component]
fn Case2() -> Html {
html! {<HelloWorld is_loading={true} />}
}

使用 Properties 的記憶體/速度開銷

內部 Properties 是參考計數的,這代表 props 只會沿著元件樹傳遞一個共享指標,讓不會因複製整個 props(成本可能會很高)而產生開銷。

提示

使用 AttrValue,作為屬性值的自訂類型,而不是將它們定義為字串或其他類似類型。

Props 巨集

yew::props! 巨集讓你可以用與 html! 巨集相同的方式建構 props。

巨集使用與結構表達式相同的語法,但你無法使用屬性或基本表達式(Foo { ..base })。類型路徑可以指向 props 本身(path::to::Props)或元件的關聯屬性(MyComp::Properties)。

use yew::{function_component, html, Html, Properties, props, virtual_dom::AttrValue};

#[derive(Properties, PartialEq)]
pub struct Props {
#[prop_or(AttrValue::from("Bob"))]
pub name: AttrValue,
}

#[function_component]
fn HelloWorld(props: &Props) -> Html {
html! {<>{"Hello world"}{props.name.clone()}</>}
}

#[function_component]
fn App() -> Html {
let pre_made_props = props! {
Props {} // Notice we did not need to specify name prop
};
html! {<HelloWorld ..pre_made_props />}
}

評估順序

Props 按指定順序評估,如下例所示

#[derive(yew::Properties, PartialEq)]
struct Props { first: usize, second: usize, last: usize }

fn main() {
let mut g = 1..=3;
let props = yew::props!(Props { first: g.next().unwrap(), second: g.next().unwrap(), last: g.next().unwrap() });

assert_eq!(props.first, 1);
assert_eq!(props.second, 2);
assert_eq!(props.last, 3);
}

反模式

雖然幾乎所有 Rust 類型都可以傳遞為 props,但有一些反模式應該避免,包括但不限於以下

  1. 使用 String 類型而非 AttrValue
    為什麼不好? String 複製的成本很高,當 prop 值與 hooks 和回呼搭配使用時,通常需要複製。AttrValue 是參考計數字串(Rc<str>)或 &'static str,因此複製成本非常低。
    注意: AttrValue 在內部是 implicit-clone 中的 IString,請參閱該 crate 以了解更多資訊。
  2. 使用內部可變性。
    為什麼不好? 一般而言,應該避免內部可變性(例如 RefCellMutex 等)。它會造成重新渲染問題(Yew 不知道狀態已變更),所以你可能必須手動強制進行一次渲染。與所有事物一樣,它有其存在的意義,請謹慎使用。
  3. 告訴我們你的看法,你是否曾遇到希望自己早一點知道的極端狀況?歡迎建立議題或 PR 來修正此文件。

yew-autoprops

yew-autoprops 是個實驗性套件,它允許你在函式的參數中動態建立 Props struct。可能會很有用,如果 properties struct 絕不會被重複使用。