5月31日 02:05

Yew 组件生命周期有哪些方法?各自适合做什么?

Yew 组件生命周期主要对应 Component trait 的几个方法:create 初始化,update 处理消息,changed 响应 props 变化,view 生成虚拟 DOM,rendered 处理真实 DOM 之后的副作用,destroy 清理资源。面试里只背方法名不够,关键要说清楚每个阶段适合放什么、不适合放什么。最容易出问题的是把副作用塞进 view,或者忘记在卸载时释放监听器和定时器。

追问

createview 分别适合做什么?

create 在组件实例创建时调用,适合根据 props 初始化字段、准备默认状态和回调需要的数据。它不适合操作 DOM,因为这时节点还没有挂载,强行查元素通常会拿到空值。view 只应该根据当前 state 和 props 返回 Html,少量格式化可以放进去,但复杂计算最好提前放到 update 或缓存字段里。

update 返回 truefalse 有什么区别?

update 收到消息后修改组件状态,返回 true 表示需要重新调用 view,返回 false 表示这次变化不影响 UI。比如计数器加一、接口数据写入 state 应该返回 true,日志上报或空操作可以返回 false。常见踩坑是所有分支都返回 true,小组件看不明显,列表页里会造成大量无意义 diff。

changed 什么时候触发,为什么不能滥用?

changed 在父组件传入的 props 变化时触发,适合根据新旧 props 判断子组件是否需要同步状态或重渲染。它的价值在于过滤无效更新,例如父组件重渲染但关键 id 没变,子组件可以返回 false。不要把所有 props 都复制成内部 state,否则很容易出现两份数据不同步;只有表单草稿、动画状态这类本地状态才值得复制。

为什么 DOM 操作要放在 rendered

rendered 在真实 DOM 更新后调用,适合读取节点尺寸、聚焦输入框,或初始化依赖节点的第三方 JS 库。first_render 能区分首次渲染,图表实例、全局监听这类只应初始化一次的逻辑必须挡住重复执行。踩坑点是每次渲染都重新挂库,最后同一个 canvas 多个实例、多个事件监听一起存在,页面会越来越慢。

destroy 主要清理哪些资源?

destroy 在组件卸载时调用,适合取消定时器、释放 JS 事件监听、关闭 WebSocket、丢弃订阅句柄。Rust 会释放普通字段,但浏览器侧事件和外部订阅不一定按你想的时机断开。边界是一次性请求通常不用专门处理,长连接、轮询、全局事件和第三方库实例必须有明确退出路径。

写段代码

rust
use yew::prelude::*; pub enum Msg { Inc, Loaded(String), Noop } pub struct Counter { count: i32, text: String } impl Component for Counter { type Message = Msg; type Properties = (); fn create(_ctx: &Context<Self>) -> Self { Self { count: 0, text: String::new() } } fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool { match msg { Msg::Inc => { self.count += 1; true } Msg::Loaded(v) => { self.text = v; true } Msg::Noop => false, } } fn view(&self, ctx: &Context<Self>) -> Html { html! { <button onclick={ctx.link().callback(|_| Msg::Inc)}>{ self.count }</button> } } fn rendered(&mut self, _ctx: &Context<Self>, first_render: bool) { if first_render { /* 初始化依赖 DOM 的逻辑 */ } } fn destroy(&mut self, _ctx: &Context<Self>) { /* 清理资源 */ } }

小结

Yew 生命周期的核心是把事情放到正确阶段:初始化在 create,状态变更在 update,属性同步在 changed,展示在 view,DOM 副作用在 rendered,资源释放在 destroy。真正写项目时,update 的返回值、rendered 的重复执行和 destroy 的清理边界,比方法定义本身更容易踩坑。

标签:Yew