web-sys
The web-sys crate provides bindings for Web APIs. This is procedurally generated from browser WebIDL which is why some names are so long and why some types are vague.
Features in web-sys#
The web-sys crate with all of its features enabled can add lots of bloat to a Wasm application. To get around this issue most types are feature gated so that you only include the types you require for your application. Yew enables several features from web-sys and exposes some types in its public API. You will often need to add web-sys as a dependency yourself.
Inheritance in web-sys#
In the Simulating inheritance section you can read how in general Rust provides an approach to simulate inheritance in JavaScript. This is very important in web-sys as understanding what methods are available on a type means understanding its inheritance.
This section is going to look at a specific element and list out its inheritance using Rust by calling Deref::deref until the value is JsValue:
use Deref;
use ;
Inheritance in web-sys in The wasm-bindgen Guide.
The Node in NodeRef#
Yew uses a NodeRef to provide a way for keeping a reference to a Node made by the html! macro. The Node part of NodeRef is referring to web_sys::Node. The NodeRef::get method will return a Option<Node> value, however, most of the time in Yew you want to cast this value to a specific element so you can use its specific methods. This casting can be done using JsCast on the Node value, if present, but Yew provides the NodeRef::cast method to perform this casting for convenience and so that you do not necessarily have to include the wasm-bindgen dependency for the JsCast trait.
The two code blocks below do essentially the same thing, the first is using NodeRef::cast and the second is using JsCast::dyn_into on the web_sys::Node returned from NodeRef::get.
- Using NodeRef::cast
- Using NodeRef::get
use HtmlInputElement;
use NodeRef;
use JsCast;
use HtmlInputElement;
use NodeRef;
JavaScript example to Rust#
This section demonstrates examples of how JavaScript code which interact with the Web APIs can be rewritten with web-sys in Rust.
JavaScript example#
document..
web-sys example#
Using web-sys alone the above JavaScript example could be implemented like this:
[dependencies]
wasm-bindgen = "0.2"
[dependencies.web-sys]
version = "0.3"
# We need to enable all the web-sys features we want to use!
features = [
"console",
"Document",
"HtmlElement",
"MouseEvent",
"DomRect",
]
use ;
use ;
let mousemove = wrap;
new
.expect
.get_element_by_id
.expect
.
.set_onmousemove;
// we now need to save the `mousemove` Closure so that when
// this event fires the closure is still in memory.
This version is much more verbose, but you will probably notice part of that is because of failure types reminding us that some of these function calls have invariants that must be held, or otherwise will cause a panic in Rust. Another part of the verbosity is the calls to JsCast to cast into different types so that you can call its specific methods.
Yew example#
In Yew you will mostly be creating Callbacks to use in the html! macro so the example is going to use this approach instead of completely copying the approach above:
[dependencies.web-sys]
version = "0.3"
# We need to enable the `DomRect` feature to use the
# `get_bounding_client_rect` method.
features = [
"console",
"HtmlElement",
"MouseEvent",
"DomRect",
]
use ;
use ;
let onmousemove = from;
html! ;
External libraries#
web-sys is a raw binding to the Web API so it comes with some pain in Rust because it was not designed with Rust or even a strong type system in mind, this is where community crates provide abstractions over web-sys to provide more idiomatic Rust APIs.