当前位置: 首页 > 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.在容器内创建一个临时目录…...

学信息系统项目管理师第4版系列06_项目管理概论

1. 项目基础 1.1. 项目是为创造独特的产品、服务或成果而进行的临时性工作 1.1.1. 独特的产品、服务或成果 1.1.2. 临时性工作 1.1.2.1. 项目有明确的起点和终点 1.1.2.2. 不一定意味着项目的持续时间短 1.1.2.3. 临时性是项目的特点&#xff0c;不是项目目标的特点 1.1…...

Java发送(QQ)邮箱、验证码发送

前言 使用Java应用程序发送 E-mail 十分简单&#xff0c;但是首先需要在项目中导入 JavaMail API 和Java Activation Framework (JAF) 的jar包。 菜鸟教程提供的下载链接&#xff1a; JavaMail mail.jar 1.4.5JAF&#xff08;版本 1.1.1&#xff09; activation.jar 1、准备…...

PostgresSQL----基于Kubernetes部署PostgresSQL

【PostgresSQL----基于Kubernetes部署PostgresSQL】 文章目录 一、创建SC、PV和PVC存储对象1.1 准备一个nfs服务器1.2 编写SC、PV、PVC等存储资源文件1.3 编写部署PostgresSQL数据库的资源声明文件 二、部署PostgresSQL2.1 部署 PV、PVC等存储对象2.2 部署PostgresSQL数据库2.3…...

7 个适合初学者的项目,可帮助您开始使用 ChatGPT

推荐&#xff1a;使用 NSDT场景编辑器快速搭建3D应用场景 从自动化日常任务到预测复杂模式&#xff0c;人工智能正在重塑行业并重新定义可能性。 当我们站在这场人工智能革命中时&#xff0c;我们必须了解它的潜力并将其整合到我们的日常工作流程中。 然而。。。我知道开始使…...

JDBC操作SQLite的工具类

直接调用无需拼装sql 注入依赖 <dependency><groupId>org.xerial</groupId><artifactId>sqlite-jdbc</artifactId><version>3.43.0.0</version></dependency>工具类 import org.sqlite.SQLiteConnection;/*** Author cpf* Dat…...

SEO百度优化基础知识全解析(了解百度SEO标签作用)

百度SEO优化的作用介绍&#xff1a; 百度SEO优化是指通过对网站的内部结构、外部链接、内容质量、用户体验等方面进行优化&#xff0c;提升网站在百度搜索结果中的排名&#xff0c;从而提高网站的曝光率和流量。通过百度SEO优化&#xff0c;可以让更多的潜在用户找到你的网站&…...

用python实现基本数据结构【03/4】

说明 如果需要用到这些知识却没有掌握&#xff0c;则会让人感到沮丧&#xff0c;也可能导致面试被拒。无论是花几天时间“突击”&#xff0c;还是利用零碎的时间持续学习&#xff0c;在数据结构上下点功夫都是值得的。那么Python 中有哪些数据结构呢&#xff1f;列表、字典、集…...

软件测试面试题汇总

测试技术面试题 软件测试面试时一份好简历的重要性 1、什么是兼容性测试&#xff1f;兼容性测试侧重哪些方面&#xff1f; 5 2、我现在有个程序&#xff0c;发现在Windows上运行得很慢&#xff0c;怎么判别是程序存在问题还是软硬件系统存在问题&#xff1f; 5 3、测试的策略…...

AP5101C 高压线性恒流IC 宽电压6-100V LED汽车大灯照明 台灯LED矿灯 指示灯电源驱动

产品描述 AP5101C 是一款高压线性 LED 恒流芯片 &#xff0c; 外围简单 、 内置功率管 &#xff0c; 适用于6- 100V 输入的高精度降压 LED 恒流驱动芯片。电流2.0A。AP5101C 可实现内置MOS 做 2.0A,外置 MOS 可做 3.0A 的。AP5101C 内置温度保护功能 &#xff0c;温度保护点为…...

【大数问题】字符串相减(大数相减)<模拟>

类似 【力扣】415. 字符串相加&#xff08;大数相加&#xff09;&#xff0c;实现大数相减。 题解 模拟相减的过程&#xff0c;先一直使大数减小数&#xff0c;记录借位&#xff0c;最后再判断是否加负号。&#xff08;中间需要删除前导0&#xff0c;例如10001-1000000001&am…...

泉州微信网站建设公司/百度首页推广

【What&#xff1f;】 Java DataBase Connectivity的缩写&#xff0c;简称为Java数据库连接。JDBC提供了一套Java中用于连接数据库的标准API。 【为什么会出现&#xff1f;】 SUN公司提供的一种数据库访问规则、规范&#xff0c;由于数据库种类较多&#xff0c;并且Java语言使用…...

3g网站app/建立一个国外的网站

由于现在家用电脑所使用的操作系统多数为WinXP 和Win2000 pro&#xff08;建议还在使用98的朋友换换系统&#xff0c;连微软都放弃了的系统你还用它干嘛&#xff1f;&#xff09;所以后面我将主要讲一下基于这两个操作系统的安全防范。 个人电脑常见的被***方式 谈到个人上网…...

wordpress移机/搜索引擎营销的四种方式

http://james.padolsey.com/demos/grayscale/转载于:https://www.cnblogs.com/jikey/archive/2010/04/21/1716893.html...

扬州集团网站建设/2022年百度seo

react-sample-javascript 为了实现一个可定制化高的react工程&#xff0c;我们往往会自己搭建一个react工程。所以本文会从零开始搭建一个react脚手架工程。解释webpack中配置的含义。基于webpack 4.0 。包含 开发环境配置&#xff0c;生产环境配置&#xff0c;代码分离&#x…...

wordpress安装后/免费网站制作成品

下了很大决心挖这个坑&#xff0c;虽然之前对kvm有些了解&#xff0c;但纸上得来终觉浅&#xff0c;只有深入到代码层面&#xff0c;才能摈弃皮毛&#xff0c;看到血肉&#xff0c;看到真相。作为挖坑的奠基石&#xff0c;准备写上几篇&#xff1a;kvm基本工作原理、CPU调度原理…...

三明市住房与城乡建设部网站/经典模板网站建设

【强制】Java 类库中定义的可以通过预检查方式规避的RuntimeException异常不应该通过catch 的方式来处理&#xff0c;比如&#xff1a;NullPointerException&#xff0c;IndexOutOfBoundsException等等。 说明&#xff1a;无法通过预检查的异常除外&#xff0c;比如&#xff0c…...