之前有写过按钮、评分组件,这次选择写一个更复杂点,于是就选了颜色选择器,之前的组件都是单一的,这次的颜色选择器组件则是好几个子组件构成的,实现部分依旧是参考Element UI的相关组件,功能方面基本上实现了跟Element UI原组件一样的功能,预设颜色没有实现,另外因为输入控件是个相对比较复杂的组件,目前使用文本来替代。
生命周期
组件的生命周期,我们可以看下Yew相关的源码,详细见源码链接。
pub trait BaseComponent: Sized + 'static {
/// The Component's Message.
type Message: 'static;
/// The Component's Properties.
type Properties: Properties;
/// Creates a component.
fn create(ctx: &Context<Self>) -> Self;
/// Updates component's internal state.
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool;
/// React to changes of component properties.
fn changed(&mut self, ctx: &Context<Self>, _old_props: &Self::Properties) -> bool;
/// Returns a component layout to be rendered.
fn view(&self, ctx: &Context<Self>) -> HtmlResult;
/// Notified after a layout is rendered.
fn rendered(&mut self, ctx: &Context<Self>, first_render: bool);
/// Notified before a component is destroyed.
fn destroy(&mut self, ctx: &Context<Self>);
/// Prepares the server-side state.
fn prepare_state(&self) -> Option<String>;
}
之前用的最多的是create、update、view这几个,这次新使用了rendered,这个提供一个是否是第一次渲染。
节点引用
fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<div class="el-color-hue-slider is-vertical">
<div ref={&self.bar_ref} class="el-color-hue-slider__bar" onclick={ctx.link().callback(|e|{
Msg::OnBarClick(e)
})}></div>
<div ref={&self.thumb_ref} class="el-color-hue-slider__thumb" style={format!("left: {}px; top: {}px", self.thumb_left, self.thumb_top)}>
</div>
</div>
}
}
之前使用Vue的时候,也经常使用这个。这次实现滑动条时,需要在更新时使用某个节点的引用,一开始使用了笨重的方式,通过ID来获取,但是很有可能ID在全局中会重复。
let document = web_sys::window().unwrap().document().unwrap();
let thumb = document
.query_selector("#thumb")
.unwrap()
.unwrap()
.dyn_ref::<HtmlElement>()
.unwrap()
.clone();
使用节点引用后则比较简单。
let thumb = self.thumb_ref.cast::<HtmlElement>().unwrap();
模块
一开始所有代码都在根目录文件夹下,文件多了自然不能这样,比如颜色选择器组件就有好几个自组件。
会发现都有mod.rs的文件,先看下components下的。
pub mod yew_color_hue_slider;
pub mod yew_picker_dropdown;
pub mod yew_sv_panel;
pub mod yew_color_alpha_slider;
比如yew_picker_dropdown.rs使用同目录下的模块。
use super::yew_color_hue_slider::YewColorHueSlider;
use super::yew_sv_panel::YewSvPanel;
use super::yew_color_alpha_slider::YewColorAlphaSlider;
再看下yew_color_picker目录下的mod.rs。
mod components;
pub mod yew_color_picker;
会发现第一个没有加pub,这样的话yew_color_picker以外就无法使用了,可以保证这些组件只是yew_color_picker在使用了。
关于这方面的内容,我感觉《Rust程序设计》这本书比《Rust权威指南》讲解的明了,更多的可以参阅此书。习惯了写Java之类,一开始确实发现有点麻烦,但我觉得这些似乎可以在IDE下得到支持。
第三方库
调试输出
目前主要使用了gloo-console这个库,再结合format!宏,非常的好用。
log!(format!("r: {}, g: {}, b:{}", rgb.0, rgb.1, rgb.2));
Math
实现中有大量加减乘除,使用最多的还是js_sys::Math这个模块。
let mut left = e.client_x() as f64 - rect.left() as f64;
left = js_sys::Math::max(thumb.offset_width() as f64 / 2.0, left);
left = js_sys::Math::min(
left,
rect.width() as f64 - thumb.offset_width() as f64 / 2.0,
);
对比Vue
实现上主要参考Element UI的源码,但是Yew和Vue还是有不少不同的地方,还是有些不同。
之前习惯了Vue的v-model,但是Yew没有这样东西,所以每次组件的值变化,总是会通过on_change这样的回调来通知父组件。
Vue提供了computed、watch这类,但是Yew中没有这些。
总的来说Yew只是提供了基本的东西,一些附加的东西还是需要自己去实现。
总结
相关的源码都在这里,喜欢的可以自己研究下。