一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
HTML
html!
html! 宏允许你为组件编写声明式的 HTML 和 SVG。语法跟React的jsx极其相似
重点
- 该html! 宏只能有一个根节点,可以使用*<></>*包裹,后面会讲到咱们再说
- 空的
html! {}会被调用,但是不渲染内容 - 常量必须用 html! { "Hello, World" } 包裹
fn view(&self, _context: &Context<Self>) -> Html {
html! {
<>
<h1 >{"我想做个好人"}</h1> //简单的字面量值也需要使用{}包一下
<h1 >{"我想做个好人"}</h1>
</>
}
}
html!宏可以轻松达到编译器的默认递归限制。如果遇到编译错误,建议增大其值。在根 crate 使用这样的属性#处理这个问题。
Components
只要是实现了 Component trait 都可以在 html! 宏中使用
use yew::{Component, Html, html, Context, Properties};
struct MyComponent;
impl Component for MyComponent {
type Message = ();
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, _ctx: &Context<Self>) -> Html {
html! {
{ "This component has no properties!" }
}
}
}
#[derive(Clone, PartialEq, Properties)]
struct Props {
prop1: String,
prop2: String,
}
struct MyComponentWithProps;
impl Component for MyComponentWithProps {
type Message = ();
type Properties = Props;
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, ctx: &Context<Self>) -> Html {
html! {
{
format!(
"prop1: {} and prop2: {}",
ctx.props().prop1,
ctx.props().prop2
)
}
}
}
}
let props = Props {
prop1: "Hello".to_owned(),
prop2: "World".to_owned(),
};
html!{
<>
// 没有 properties
<MyComponent />
// 有 Properties
<MyComponentWithProps prop1="lorem" prop2="ipsum" />
// 同时设定整个 props provided
<MyComponentWithProps ..props.clone() />
// 变量的属性和特定值被覆盖
<MyComponentWithProps prop2="lorem" ..props />
</>
};
如果 Properties 中包含children,则可以访问和更改嵌套组件的属性
use yew::{Children, Component, Context, html, Html, Properties};
#[derive(PartialEq, Properties)]
struct Props {
id: String,
children: Children,
}
struct Container;
impl Component for Container {
type Message = ();
type Properties = Props;
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<div id={ctx.props().id.clone()}>
{ ctx.props().children.clone() }
</div>
}
}
}
html! {
<Container id="container">
<h4>{ "Hi" }</h4>
<div>{ "Hello" }</div>
</Container>
};
html!宏可以使用表达式,..props把全部属性补充到属性上,此表达式必须在单独属性之后. html!中的children 会覆盖props 中的children;代码如下
use yew::{Children, Component, Context, html, Html, props, Properties};
#[derive(PartialEq, Properties)]
struct Props {
id: String,
children: Children,
}
struct Container;
impl Component for Container {
type Message = ();
type Properties = Props;
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<div id={ctx.props().id.clone()}>
{ ctx.props().children.clone() }
</div>
}
}
}
let props = yew::props!(Container::Properties {
id: "container-2",
children: Children::default(),
});
html! {
<Container ..props>
// props.children 会被下面这一行覆盖
<span>{ "I am a child, as you can see" }</span>
</Container>
};
嵌套Children 的Props
如果包含组件标注了 children 的类型,则可以访问和更改嵌套组件的属性,
在下面的示例中,List 组件可以包含 ListItem 组件
use std::rc::Rc;
use yew::{html, ChildrenWithProps, Component, Context, Html, Properties};
#[derive(Clone, PartialEq, Properties)]
pub struct ListItemProps {
value: String,
}
pub struct ListItem;
impl Component for ListItem {
type Message = ();
type Properties = ListItemProps;
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<span>
{ ctx.props().value.clone() }
</span>
}
}
}
#[derive(PartialEq, Properties)]
pub struct Props {
pub children: ChildrenWithProps<ListItem>,
}
pub struct List;
impl Component for List {
type Message = ();
type Properties = Props;
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, ctx: &Context<Self>) -> Html {
html! {{
for ctx.props().children.iter().map(|mut item| {
let mut props = Rc::make_mut(&mut item.props);
props.value = format!("item-{}", props.value);
item
})
}}
}
}
html! {
<List>
<ListItem value="a" />
<ListItem value="b" />
<ListItem value="c" />
</List>
};