Router

The router on crates.io

Routers in Single Page Applications (SPA) handle displaying different pages depending on what the URL is. Instead of the default behavior of requesting a different remote resource when a link is clicked, the router instead sets the URL locally to point to a valid route in your application. The router then detects this change and then decides what to render.

Core Elements

Route

Contains a String representing everything after the domain in the url and optionally the state stored in the history API.

RouteService

Communicates with the browser to get and set Routes.

RouteAgent

Owns a RouteService and is used to coordinate updates when the route changes, either from within the application logic or from an event fired from the browser.

Switch

The Switch trait is used to convert a Route to and from the implementer of this trait.

Router

The Router component communicates with RouteAgent and will automatically resolve Routes it gets from the agent into switches, which it will expose via a render prop that allows specifying how the resulting switch gets converted to Html.

How to use the router

First, you want to create a type that represents all the states of your application. Do note that while this typically is an enum, structs are supported as well, and that you can nest other items that implement Switch inside.

Then you should derive Switch for your type. For enums, every variant must be annotated with #[at = "/some/route"], or if you use a struct instead, that must appear outside the struct declaration.

  1. #[derive(Switch)]
  2. enum AppRoute {
  3. #[at = "/login"]
  4. Login,
  5. #[at = "/register"]
  6. Register,
  7. #[at = "/delete_account"]
  8. Delete,
  9. #[at = "/posts/{id}"]
  10. ViewPost(i32),
  11. #[at = "/posts/view"]
  12. ViewPosts,
  13. #[at = "/"]
  14. Home
  15. }

Router - 图1

caution

Do note that the implementation generated by the derive macro for Switch will try to match each variant in order from first to last, so if any route could possibly match two of your specified at annotations, then the first one will match, and the second will never be tried. For example, if you defined the following Switch, the only route that would be matched would be AppRoute::Home.

  1. #[derive(Switch)]
  2. enum AppRoute {
  3. #[at = "/"]
  4. Home,
  5. #[at = "/login"]
  6. Login,
  7. #[at = "/register"]
  8. Register,
  9. #[at = "/delete_account"]
  10. Delete,
  11. #[at = "/posts/{id}"]
  12. ViewPost(i32),
  13. #[at = "/posts/view"]
  14. ViewPosts,
  15. }

You can also capture sections using variations of {} within your #[at = ""] annotation. {} means capture text until the next separator (either “/“, “?”, “&”, or “#” depending on the context). {*} means capture text until the following characters match, or if no characters are present, it will match anything. {<number>} means capture text until the specified number of separators are encountered (example: {2} will capture until two separators are encountered).

For structs and enums with named fields, you must specify the field’s name within the capture group like so: {user_name} or {*:age}.

The Switch trait works with capture groups that are more structured than just Strings. You can specify any type that implements Switch. So you can specify that the capture group is a usize, and if the captured section of the URL can’t be converted to it, then the variant won’t match.