当前位置: 首页 > news >正文

Rust Yew应用开发的事件初探

在Rust的世界中有一个叫Yew的框架,它借鉴了React的思想。我的React代码也写了不少,今天就聊一下我个人对Yew应用开发中事件相关部分的体验。

我的也是才开始学习Rust和Yew,说得不对的地方还请大家多多指教。

下面的例子涉及到3个组件
ParentComponent组件
Button组件
<button/>原生html元素
也就是说,在ParentComponent组件中放置了Button组件,这个Button组件其实就是对<button/>的一个封装。这里的事件传递就是
<button/> -> Button -> ParentComponent

先从Button组件中的点击事件说起。

按钮事件定义如下

use yew::{Properties, Callback, MouseEvent};#[derive(Properties, PartialEq)]
pub struct Props {#[prop_or_default]pub onclick: Callback<MouseEvent>,
}

这里上面关于事件的onclick,虽然就2行代码,但这里面的信息量比较大,我将为大家逐一分析,以能知其所以然。

Properties

用于定义组件的参数,和React一样,当组件的参数更新时,Yew框架会自动更新组件。
在Yew框架中,通过结构体(struct)来定义组件的参数。在这个结构体中,你可以定义各种类型的字段,这些字段对应的就是组件的参数。
Properties本身是一个tarit,但并不需要我们开发人员来实现这个trait。Yew框架通过Rust的derive功能,自动将Properties的实现和你定义的结构体结合起来。
在结构体的字段中,就包含了我们要讨论的事件Callback。
也就是说,我们的事件就可以定义成下面这个样子。

#[derive(Properties)]
pub struct Props {pub onclick: Callback<()>,
}

PartialEq

和Properties一样,PartialEq也是一个trait,如果大家结合React的组件更新逻辑,估计能够猜得出来它的用意。是的,它就是Yew框架用来比较属性值,看其是否有更新。不过你完全不必担心自己忘记加上这个trait,因为编译器的错误报告会提醒你。这也是我喜欢Rust的地方。

Callback

用于定义组件暴露出来的事件。它的声明形式如下:

pub struct Callback<IN, OUT = ()> { /* private fields */ }

当我们定义一个空事件时,代码就是这样:

pub onclick: Callback<()>

在Yew应用开发中,通常用Callback<>来定义事件,因为Yew框架本身用Callback类型包装了html元素的事件。使用Callback类型来定义事件比较方便和安全。

prop_or_default

prop_or_default其实不是必须的。如果你不为你的字段添加这个attribute 宏,就必须在使用这个组件的地方为它设置值,否者会编译报错。这对组件的使用者来说显然不太友好。
因此,这里我们使用到了prop_or_default,它可以帮助Yew框架,在运行时,如果没有为事件字段赋值,系统会为其计算推导出默认值。
在Yew框架中,除了prop_or_default,还有prop_or(value)和prop_or_else(function)。
prop_or_default: 使用类型的默认值
prop_or(value): 使用给定的默认值
prop_or_else(function): 通过函数来获取默认值

MouseEvent

yew::MouseEvent实际上是从web_sys中导出的,它包含了鼠标当前的位置信息。具体可以参考https://docs.rs/web-sys/0.3.60/web_sys/struct.MouseEvent.html
之所以把MouseEvent提出来,是为了让大家对Yew中的Html的事件参数有一个初步的了解。

pub use web_sys::AnimationEvent;
pub use web_sys::DragEvent;
pub use web_sys::ErrorEvent;
pub use web_sys::Event;
pub use web_sys::FocusEvent;
pub use web_sys::InputEvent;
pub use web_sys::KeyboardEvent;
pub use web_sys::MouseEvent;
pub use web_sys::PointerEvent;
pub use web_sys::ProgressEvent;
pub use web_sys::SubmitEvent;
pub use web_sys::TouchEvent;
pub use web_sys::TransitionEvent;
pub use web_sys::UiEvent;
pub use web_sys::WheelEvent;

上面说了这么多关于Yew事件定义,接下来看看如何从原生的<button/> html元素上获取事件吧。
使用方式和React几乎是一样的,开发过React项目的同学是不是觉得很亲切啊。

  <button style={danger_style} onclick={props.onclick.clone()}>{props.text.clone()}</button>

Button.rs的完整代码如下:

use yew::{function_component, html, Callback, Html, MouseEvent, Properties};#[derive(PartialEq)]
pub enum DisplayType {Default,Danger,
}#[derive(Properties, PartialEq)]
pub struct Props {#[prop_or_default]pub text: String,#[prop_or(DisplayType::Default)]pub display_type: DisplayType,#[prop_or_default]pub onclick: Callback<MouseEvent>,
}static default_style: &str = "..."; //隐藏不必要代码
static danger_style: &str = "..."; //隐藏不必要代码#[function_component]
pub fn Button(props: &Props) -> Html {match props.display_type {DisplayType::Danger => html! {<button style={danger_style} onclick={props.onclick.clone()}>{props.text.clone()}</button>},DisplayType::Default => html! {<button style={default_style} onclick={props.onclick.clone()}>{props.text.clone()}</button>},}
}

在上面的Button.rs中,我们创建了组件Button,并为其定义了事件onclick,下面就来看如何消费这个事件。

这里我想稍作停顿。我们知道Yew借鉴了React的思想,可以看到两者间很多的相似之处。但是毕竟Yew是基于Rust语言开发的,而React(这里特指ReactJs)是基于Javascript开发的。前者是静态编译语言,后者是动态语言。
因此,在Reat中,如何要处理Button中的onclick事件,代码应该像下面这个样子:

<Button onclick={()=>console.log('clicked')}/>

但是在Yew中,代码就没有简单了。
没关系,只要知其所以然,其实Yew中的事件处理也很简单。

在Yew应用开发中,处理事件的步骤如下:

  1. 定义事件枚举
  2. 将事件枚举绑定到要处理的组件事件上
  3. 在当前组件的update方法中处理事件

下面的代码用struct组件为例来展示如何处理Button上的onclick事件。

定义事件枚举

use yew::{ Component }
enum ParentComponentMsg {Toggle,
}pub struct ParentComponent;impl Component for ParentComponent {type Message = ParentComponentMsg;
}

在上面的代码中,按照Yew的惯例,将事件枚举的名称定义为"组件名称"+Msg,建议大家也遵守这个惯例。
然后不要忘记,对于初学者来说很容易忘记下面这行代码:

type Message = ParentComponentMsg;

这行代码是告诉编译器,ParentComponent使用的事件枚举的类型。如果没有这行代码,或者这行代码是"type Message = ();",在下一个步骤上,编译器会报错。

    the trait `std::convert::From<components::base::parentComponent::ParentComponentMsg>` is not implemented for `()`

将事件枚举绑定到要处理的组件事件上

这里我们要处理Button组件的onclick事件,代码如下:

    fn view(&self, ctx: &Context<Self>) -> Html {let onclick = ctx.link().callback(|_| ParentComponentMsg::Toggle);html! {<div class="modal"><Button text="点击" onclick={onclick}/></div>}}

上面的参数中,Context的出现频率很高,它用于获取当前组件的属性值,以及处理事件相关的处理。后面有机会再展开说说。

在当前组件的update方法中处理事件

    fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {match msg {ParentComponentMsg::Toggle => {log!("clicked");// 可以在这里修改self上的属性,即改变组件本身的状态,来触发新的渲染。这就是react的做法了。}}true}

让我再来夸夸Rust,它利用它的mut关键字来告诉编译器,这个对象是可修改的。如果没有mut关键字,但有修改对象属性的代码,编译器会直接报错。这一点在ReactJs中是做不到的。在ReactJs中,我们只能严格遵守只能通过setXXX来修改状态,但如果你鬼使神差地直接修改了状态值,一般情况下好像也没有报错(我不确定某些eslint插件是否具有这个功能)。

相比于ReactJs,要处理一个事件要多些这么多的代码,是有点不方便,但是如果你的代码写错了,编译器会报错,这里总算挽回了一点面子。

好了,关于《Rust Yew应用开发的事件初探》我就写在这里了。这真的是一个初探,里面的见解比较粗浅,因为我也是边学边用。我要去写我的项目去了,有什么新发现我再来和大家分享。

有不对的地方还请大家留言指教。

相关文章:

Rust Yew应用开发的事件初探

在Rust的世界中有一个叫Yew的框架&#xff0c;它借鉴了React的思想。我的React代码也写了不少&#xff0c;今天就聊一下我个人对Yew应用开发中事件相关部分的体验。 我的也是才开始学习Rust和Yew&#xff0c;说得不对的地方还请大家多多指教。 下面的例子涉及到3个组件 Paren…...

高并发下单例线程安全

1.使用静态内置类实现单例模式 自定义线程池 2.使用static代码块实现单例 3.使用静态内置类实现单例模式 4.使用static代码块实现单例 public class MySingleton {//使用volatile关键字保其可见性volatile private static MySingleton instance null;private MySingleton…...

【EKF】EKF原理

原理简述 卡尔曼滤波可以在线性模型&#xff0c;误差为高斯模型的情况下&#xff0c;对目标状态得出很好的估计效果&#xff0c;但如果系统存在非线性的因素&#xff0c;其效果就没有那么好了。比较典型的非线性函数关系包括平方关系&#xff0c;对数关系&#xff0c;指数关系…...

蓝桥杯官网填空题(古堡算式)

题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 福尔摩斯到某古堡探险&#xff0c;看到门上写着一个奇怪的算式&#xff1a;ABCDE ∗ ?EDCBA 他对华生说&#xff1a;“ABCDE 应该代表不同的数字&#xff0c;问号…...

Python---集合set

集合特点 1. 可以容纳多个数据 2. 可以容纳不同类型的数据 3.数据是无序存储的&#xff08;不支持下标索引&#xff09; 4. 不允许重复数据存在 5. 可以修改 6. 支持for循环&#xff0c;不支持while循环 集合定义 # 定义集合 变量 {元素1, 元素2, 元素3, 元素4...}# 定…...

LORA项目源码解读

大模型fineturn技术中类似于核武器的LORA&#xff0c;简单而又高效。其理论基础为&#xff1a;在将通用大模型迁移到具体专业领域时&#xff0c;仅需要对其高维参数的低秩子空间进行更新。基于该朴素的逻辑&#xff0c;LORA降低大模型的fineturn门槛&#xff0c;模型训练时不需…...

Azure + React + ASP.NET Core 项目笔记一:项目环境搭建(一)

不重要的目录标题 前提条件第一步&#xff1a;新建文件夹第二步&#xff1a;使用VS/ VS code/cmd 打开该文件夹第三步&#xff1a;安装依赖第四步&#xff1a;试运行react第五步&#xff1a;整理项目结构 前提条件 安装dotnet core sdk 安装Node.js npm 第一步&#xff1a;新…...

html 学习 之 文本标签

下面是一些常见的HTML文本标签&#xff08;&#xff0c;&#xff0c;&#xff0c;&#xff0c;和&#xff09;以及它们的作用&#xff1a; 标签 (Emphasis - 强调): 作用&#xff1a;用于在文本中表示强调或重要性。 示例&#xff1a; <p>这是一段文本&#xff0c;&l…...

联发科3纳米芯片预计2024年量产,此前称仍未获批给华为供货

9月7日&#xff0c;联发科与台积电共同宣布&#xff0c;联发科首款采用台积电3纳米制程生产的天玑旗舰芯片开发进度顺利&#xff0c;已成功流片&#xff0c;预计将在2024年量产&#xff0c;并将于下半年正式上市。这款旗舰芯片并非今年上市的天玑9300。 据联发科总经理陈冠州介…...

搭建vue3项目并git管理

搭建vue3项目 采用vue3的create-vue脚手架搭建项目&#xff0c;底层是vite&#xff0c;要求环境 node 16.0及以上&#xff08;node -v检查node版本&#xff09; 在文件夹右键->终端-> npm init vuelatest&#xff0c;输入项目名称&#xff0c;根据需要选择是否装包 src…...

【Azure OpenAI】OpenAI Function Calling 101

概述 本文是结合 github&#xff1a;OpenAI Function Calling 101在 Azure OpenAI 上的实现&#xff1a; Github Function Calling 101 如何将函数调用与 Azure OpenAI 服务配合使用 - Azure OpenAI Service 使用像ChatGPT这样的llm的困难之一是它们不产生结构化的数据输出…...

立晶半导体Cubic Lattice Inc 专攻音频ADC,音频DAC,音频CODEC,音频CLASS D等CL7016

概述&#xff1a; CL7016是一款高保真USB Type-C兼容音频编解码芯片。可以录制和回放有24比特音乐和声音。内置回放通路信号动态压缩&#xff0c; 最大42db录音通路增益&#xff0c;PDM数字麦克风&#xff0c;和立体声无需电容耳机驱动放大器。 5V单电源供电。兼容USB 2.0全速工…...

【Flutter】支持多平台 多端保存图片到本地相册 (兼容 Web端 移动端 android 保存到本地)

免责声明: 我只测试了Web端 和 Android端 可行哈 import dart:io; import package:flutter/services.dart; import package:http/http.dart as http; import package:universal_html/html.dart as html; import package:oktoast/oktoast.dart; import package:image_gallery_sa…...

postgresql 安装教程

postgresql 安装教程 本文以window 15版本为教程 文章目录 postgresql 安装教程1.下载地址2.以管理员身份运行3.选择安装路径&#xff0c;点击Next4.选择组件&#xff08;默认都勾选&#xff09;&#xff0c;点击Next5.选择数据存储路径&#xff0c;点击Next6.设置超级用户的…...

手写数据库连接池

数据库连接是个耗时操作.对数据库连接的高效管理影响应用程序的性能指标. 数据库连接池正是针对这个问题提出来的. 数据库连接池负责分配,管理和释放数据库连接.它允许应用程序重复使用一个现有的数据路连接,而不需要每次重新建立一个新的连接,利用数据库连接池将明显提升对数…...

在CentOS7上增加swap空间

在CentOS7上增加swap空间 在CentOS7上增加swap空间&#xff0c;可以按照以下步骤进行操作&#xff1a; 使用以下命令检查当前swap使用情况&#xff1a; swapon --show创建一个新的swap文件。你可以根据需要指定大小。例如&#xff0c;要创建一个2GB的swap文件&#xff0c;使用…...

@Autowired和@Resource

文章目录 简介Autowired注解什么是Autowired注解Autowired注解的使用方式Autowired注解的优势和不足 Qualifier总结&#xff1a; Resource注解什么是Resource注解Resource注解的使用方式Resource注解的优势和不足 Autowired vs ResourceAutowired和Resource的区别为什么推荐使用…...

QTableView通过setColumnWidth设置了列宽无效的问题

在用到QT的QTableView时&#xff0c;为了显示效果&#xff0c;向手动的设置每一列的宽度&#xff0c;但是如下的代码是无效的。 ui->tableView->setColumnWidth(0,150);ui->tableView->setColumnWidth(1,150);ui->tableView->setColumnWidth(2,150);ui->t…...

【用unity实现100个游戏之10】复刻经典俄罗斯方块游戏

文章目录 前言开始项目网格生成Block方块脚本俄罗斯方块基类&#xff0c;绘制方块形状移动逻辑限制移动自由下落下落后设置对应风格为不可移动类型检查当前方块是否可以向指定方向移动旋转逻辑消除逻辑游戏结束逻辑怪物生成源码参考完结 前言 当今游戏产业中&#xff0c;经典游…...

Docker容器内数据备份到系统本地

Docker运行容器时没将目录映射出来&#xff0c;或者因docker容器内外数据不一致&#xff0c;导致docker运行错误的&#xff0c;可以使用以下步骤处理&#xff1a; 1.进入要备份的容器&#xff1a; docker exec -it <容器名称或ID> /bin/bash2.在容器内创建一个临时目录…...

基于Jina Reader与Exa API的免费网页抓取与搜索工具实践

1. 项目概述&#xff1a;一个轻量级的网络信息抓取与处理工具最近在折腾一些自动化信息处理的项目&#xff0c;发现很多时候需要从网上快速抓取内容或者进行关键词搜索&#xff0c;然后对结果进行结构化处理。市面上的工具要么太重&#xff0c;要么收费&#xff0c;要么就是API…...

Markdown元数据自动化管理:mdac-filler工具核心功能与实战指南

1. 项目概述&#xff1a;一个为Markdown文档自动填充元数据的工具如果你经常用Markdown写文档、博客或者项目README&#xff0c;肯定遇到过这样的场景&#xff1a;每次新建一个文件&#xff0c;都得手动去文件头部敲一堆“Front Matter”元数据&#xff0c;比如标题、日期、标签…...

专业级macOS歌词同步方案:LyricsX核心功能深度解析

专业级macOS歌词同步方案&#xff1a;LyricsX核心功能深度解析 【免费下载链接】LyricsX &#x1f3b6; Ultimate lyrics app for macOS. 项目地址: https://gitcode.com/gh_mirrors/ly/LyricsX LyricsX是一款专为macOS设计的专业级歌词同步工具&#xff0c;通过智能歌词…...

ImageTrans插件生态:用Python扩展图片OCR与翻译工作流

1. 项目概述&#xff1a;一个为ImageTrans量身定制的插件生态如果你经常需要处理图像中的文字&#xff0c;比如翻译漫画、本地化游戏截图或者处理带文字的UI设计稿&#xff0c;那你很可能听说过或者用过ImageTrans这款工具。它是一款专注于图片文字识别&#xff08;OCR&#xf…...

为个人开源项目寻找高性价比大模型API的选型与实践

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 为个人开源项目寻找高性价比大模型API的选型与实践 对于个人开发者或学生而言&#xff0c;运营一个GitHub开源项目常常需要在有限的…...

汽车后市场品牌营销路径:以奇正沐古和康明斯为例

在汽车后市场&#xff0c;很多品牌真正的难题并非没有技术、没有产品、没有资源&#xff0c;而是这些优势到了终端之后&#xff0c;无法变成司机、经销商和维修点愿意相信、愿意推荐、愿意购买的理由。康明斯发动机润滑油就是个典型例子&#xff0c;康明斯作为全球柴油发动机技…...

本地化AI代码助手部署指南:从模型选型到性能调优

1. 项目概述&#xff1a;一个面向开发者的本地化AI代码助手最近在GitHub上看到一个挺有意思的项目&#xff0c;叫“JPeetz/Hermes-Studio”。乍一看名字&#xff0c;可能会联想到希腊神话里的信使赫尔墨斯&#xff0c;或者某个设计软件。但点进去你会发现&#xff0c;这其实是一…...

D26: 向下负责——保护团队免受 AI 焦虑影响

文章目录 D26: 向下负责——保护团队免受 AI 焦虑影响 🎯 为什么这个话题重要? 现实痛点:团队 AI 焦虑的三种表现 一个真实场景 一、理解 AI 焦虑的本质 1.1 焦虑从何而来? 1.2 焦虑的恶性循环 1.3 一个心理学视角 二、建立团队心理安全网 2.1 心理安全:团队韧性的基石 2…...

图解人工智能(10)人工智能的发展历程

人工智能自20世纪50年代发展至今&#xff0c;经历了若干次高潮和低谷。每到陷入困境的时候&#xff0c;总有一些科学家勇敢地打破传统思想的束缚&#xff0c;创造出新理论、新方法&#xff0c;使人工智能重现生机。例如&#xff0c;在符号主义陷入危机的时候&#xff0c;费根鲍…...

在株洲如何根据个人需求选择合适的床垫?

如何根据个人需求选择合适的床垫&#xff1f;在快节奏的现代生活中&#xff0c;一张舒适的床垫对于保证良好的睡眠质量至关重要。然而&#xff0c;面对市场上琳琅满目的床垫产品&#xff0c;如何根据个人需求选择一款合适的床垫呢&#xff1f;本文将从多个维度出发&#xff0c;…...