Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API ergonomics #133

Closed
sophiajt opened this issue Feb 20, 2018 · 6 comments
Closed

API ergonomics #133

sophiajt opened this issue Feb 20, 2018 · 6 comments

Comments

@sophiajt
Copy link

sophiajt commented Feb 20, 2018

Great work! Definitely very cool.

Looking through the TodoMVC example, there are some places that could use a bit of tightening to give them the same "lightness" of the equivalent JS.

Here's one:

    // Select the filter "button".
    let filter_anchors = document().query_selector_all( ".filters a" ).unwrap();
    for anchor in &filter_anchors {
        let anchor: Element = anchor.try_into().unwrap();
        anchor.class_list().remove( "selected" ).unwrap();
    }

And the equivalent JS:

$(".filters a").removeClass("selected")

While the Rust might not get quite that small, a bit of API "golf" I think could help it feel as easy to use as jQuery or equivalent libraries.

Alternatively, maybe we need a jQuery-like library that sits on top of stdweb?

@koute
Copy link
Owner

koute commented Feb 20, 2018

Yep. The ergonomics of stdweb itself are definitely lacking here and there, however creating additional abstraction layers over the Web APIs is, I think, out-of-scope of stdweb itself. Its low-levelness is deliberate, and while I wouldn't call it fat-free right now I'll be definitely trying to make it more lean in the future (e.g. reduce the code bloat, make it faster, simplify some internal machinery related to the js! macro, split out what is currently in webcore and webapi directories into separate crates, etc.).

That said, I would very much welcome something higher level (and more ergonomic) as a companion crate based on stdweb, maybe even have it live in the same repository to ensure compatibility.

@sophiajt
Copy link
Author

Makes perfect sense. I'll go ahead and close this.

You mention "maybe even have it live in the same repository to ensure compatibility". How often is stdweb changing these days? Sounds like you think it'll be too difficult to track changes.

@koute
Copy link
Owner

koute commented Feb 20, 2018

We had quiet a few breaking changes lately (see the changelog in the README for what's going to break in 0.4 which I'm going to release soon), but hopefully we won't break that often. I fully intend to stabilize things around going forward. (Sometimes breaking changes are unfortunately unavoidable as we figure out the best ways to do something or our previous assumptions are invalidated; the API surface when dealing with the Web and the JavaScript is huge.)

I actually don't think it would be too difficult to track any future breaking changes; every breaking change is going to be documented in our changelog anyway. It would just be somewhat easier to have it in the same repository, and would ensure that the stdweb and the higher level crate are kept in sync all the time (both crates' tests would be run at the same time, etc.).

@sophiajt
Copy link
Author

Sounds good. Thanks, @koute

@Pauan
Copy link
Contributor

Pauan commented Feb 20, 2018

@jonathandturner That's not a fair comparison, since your "JavaScript" example is using jQuery, which is a quite large (and slow) dependency. This would be the fair comparison:

let filter_anchors = document().query_selector_all(".filters a").unwrap();
for anchor in &filter_anchors {
    let anchor: Element = anchor.try_into().unwrap();
    anchor.class_list().remove("selected").unwrap();
}
var filterAnchors = document.querySelectorAll(".filters a");
for (let anchor of filterAnchors) {
    anchor.classList.remove("selected");
}

The primary differences between them is that Rust has more verbose (but more correct) error-handling (e.g. unwrap), and Rust has to manually cast between the different HTML types (using .try_into()), because it has static typing. Otherwise the two examples are quite similar.

Having said that, you are completely right that the current APIs are complex (mostly because the equivalent DOM APIs are complex). I am currently working on a Virtual DOM implementation on top of stdweb which should help out a lot with that.

@Pauan
Copy link
Contributor

Pauan commented Mar 27, 2018

Earlier I had mentioned creating a virtual DOM library for stdweb, and I have finally published it to crates.io. You can use it like this:

html!("div", {
    event(|e: ClickEvent| {
        ...
    });
    children(&mut [
        html!("div", {
            style("width", "50px");
            style("height", "50px");
            style("background-color", "green");
        }),
    ]);
})

It has a ton of other useful stuff as well.

You can read more about it here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants