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:
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:
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:
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.