Defining and Navigating Routes

Routes are an array passed to new Framework7 572,986 ({ routes }) and shared by every view. Each has a path, an optional name, and one content source. The router tests them top to bottom and loads the first match:

src/js/routes.js with the book detail routeJavaScript
import HomePage from '../pages/home.f7';
import BookPage from '../pages/book.f7';
import NotesPage from '../pages/notes.f7';
import CatalogPage from '../pages/catalog.f7';
import CartPage from '../pages/cart.f7';
import NotFoundPage from '../pages/404.f7';
const routes = [
  { path: '/', name: 'home', component: HomePage, alias: '/home/' },
  { path: '/books/:id(\\d+)/', name: 'book', component: BookPage,
    routes: [{ path: 'notes/', name: 'notes', component: NotesPage }] },
  { path: '/latest/', redirect: '/books/4/' },
  { path: '/catalog/', name: 'catalog', component: CatalogPage }, // the tabs of Section 2.5.5
  { path: '/cart/', name: 'cart', component: CartPage },
  { path: '(.*)', component: NotFoundPage }, // must stay last
];
export default routes;

The book route keeps this path; Async Routes swaps its component for an async loader, and Routable Tabs Configuration turns the nested notes route into a routable tab.

The router intercepts link clicks inside a view, so each catalog row becomes <a href="/books/${book.id}/" class="item-link item-content">, and <a href="#" class="link back"> calls router.back(). Attributes such as data-animate="false" or data-view=".view-main" carry options, and the prevent-router class opts a link out. Router events bubble to the app, so two handlers log every navigation:

Route event handlers added to the constructor in src/js/app.jsJavaScript
  on: {
    routeChange(to, from) {
      const name = to.name || 'unnamed';
      console.log(`routeChange  ${from.url || '(start)'} -> ${to.url} [${name}]`);
    },
    routeChanged(to, from, router) {
      console.log(`routeChanged history=${JSON.stringify(router.history)}`);
    },
  },

Tapping Salt and Saffron, its notes, Back twice and Staff pick (Passing Data Between Pages) in Playwright-driven Chrome 1 logs:

Output of 22
routeChange  (start) -> / [home]
routeChange  (start) -> /catalog/ [catalog]
routeChange  (start) -> /cart/ [cart]
book.f7 props={"id":"3"} query={}
routeChange  / -> /books/3/ [book]
routeChanged history=["/","/books/3/"]
routeChange  /books/3/ -> /books/3/notes/ [notes]
routeChanged history=["/","/books/3/","/books/3/notes/"]
routeChange  /books/3/notes/ -> /books/3/ [book]
routeChanged history=["/","/books/3/"]
routeChange  /books/3/ -> / [home]
routeChanged history=["/"]
book.f7 props={"id":"5","badge":"Staff pick"} query={"from":"pick"}
routeChange  / -> /books/5/?from=pick [book]
routeChanged history=["/","/books/5/?from=pick"]

Each tab's view logged its first route. Going back did not log a second book.f7 line: the router reused the page it had kept in the DOM. routeChange fires after the page component has run, routeChanged when the transition ends.