表单处理
2026/5/21小于 1 分钟euvuirustwasmusage-introductionform
文本输入
let username: Signal<String> = use_signal(|| "".to_string());
let username_updater: Signal<String> = username;
html! {
input {
r#type: "text"
placeholder: "Enter username"
value: username
oninput: move |event: Event| {
if let Some(target) = event.target()
&& let Ok(input) = target.clone().dyn_into::<HtmlInputElement>() {
username_updater.set(input.value());
}
}
}
}复选框
let agree: Signal<bool> = use_signal(|| true);
let agree_updater: Signal<bool> = agree;
html! {
input {
r#type: "checkbox"
checked: agree
onchange: move |event: Event| {
if let Some(target) = event.target()
&& let Ok(input) = target.clone().dyn_into::<HtmlInputElement>() {
agree_updater.set(input.checked());
}
}
}
label { "I agree to the terms" }
}提示
复选框必须使用 onchange 而非 oninput 监听变化。通过 event.target() 获取 DOM 元素后,用 dyn_into::<HtmlInputElement>() 读取 checked 属性。
表单验证
let errors: Signal<String> = use_signal(|| "".to_string());
let submitted: Signal<String> = use_signal(|| "".to_string());
button {
onclick: move |_event: Event| {
let mut validation_errors: Vec<String> = Vec::new();
if username.get().trim().is_empty() {
validation_errors.push("Username is required".to_string());
}
if email.get().trim().is_empty() {
validation_errors.push("Email is required".to_string());
}
if validation_errors.is_empty() {
errors.set("".to_string());
submitted.set(format!("Submitted: {}", username.get()));
} else {
errors.set(validation_errors.join("; "));
}
}
"Submit"
}注意
onsubmit 事件中需要自行阻止默认提交行为(event.prevent_default()),否则页面会刷新。