Nested Pages/Routes
In ofa.js, nested pages (also known as nested routes) are a powerful feature that allows you to create a page structure with parent-child hierarchy. The parent page serves as a layout container, rendering the content of the child page through the <slot> element.
Basic Concepts
- Parent Page (Layout): The page that serves as the layout container, containing common UI elements such as the navigation bar and sidebar
- Child Page: The specific business page content, which will be rendered into the
<slot>position of the parent page
How to Write the Parent Page
The parent page needs to use the <slot></slot> tag to reserve a rendering position for the child page.
<!-- layout.html -->
<template page>
<style>
:host {
display: block;
height: 100%;
}
...
</style>
...
<div class="content">
<slot></slot>
</div>
...
</template>
How to write subpages
The child page specifies the parent page path by exporting the parent attribute.
<template page>
<style>
:host {
display: block;
border: 1px solid red;
padding: 10px;
}
</style>
<p>{{val}}</p>
<script>
export const parent = 'layout.html'; // ⚠️ key code
export default async () => {
return {
data: {
val: "Hello ofa.js Demo Code",
},
};
};
</script>
</template>
Nested Page Example
Below is a complete nested routing example, including root layout, parent page, and child page:
// Application homepage URL
export const home = "./sub-page01.html";
// Page transition animation configuration
export const pageAnime = {
current: {
opacity: 1,
transform: "translate(0, 0)",
},
next: {
opacity: 0,
transform: "translate(30px, 0)",
},
previous: {
opacity: 0,
transform: "translate(-30px, 0)",
},
};
I am Sub-page 1
Current route: {{src}}
Jump to Page 2
I am Sub-page 2
Current route: {{src}}
Jump to Page 1
Route monitoring of the parent page
The parent page can listen to route changes through the routerChange lifecycle hook, which is very useful when you need to update the navigation state based on the current route.
<template page>
...
<script>
export default () => {
return {
data: {
active1: false,
active2: false,
},
routerChange() {
this.refreshActive();
},
ready() {
this.refreshActive();
},
proto: {
refreshActive() {
const { current } = this.app;
const path = new URL(current.src).pathname;
this.active1 = path.includes('page1');
this.active2 = path.includes('page2');
},
},
};
};
</script>
</template>
Notes
parentattribute value can be a relative path (e.g.,./layout.html) or an absolute path (e.g.,/pages/layout.html)- The parent page must contain a
<slot></slot>tag, otherwise the child page content will not be displayed - The parent page's styles will be inherited by the child page, and the child page can also define its own styles
- Using the
routerChangehook can listen to route changes, enabling functions like navigation highlighting
Multi-level Nesting
A parent page can also have its own parent page, forming a multi-level nested structure.
<!-- subpage -->
<template page>
<p>Subpage content</p>
<script>
export const parent = './parent.html';
export default () => {
return { data: {} };
};
</script>
</template>
<!-- Parent page -->
<template page>
<div class="layout">
<nav>Navigation bar</nav>
<slot></slot>
</div>
<script>
export const parent = './root-layout.html';
export default () => {
return { data: {} };
};
</script>
</template>
Multi-level Nesting Example
// Application home address
export const home = "./sub-page01.html";
// Page transition animation configuration
export const pageAnime = {
current: {
opacity: 1,
transform: "translate(0, 0)",
},
next: {
opacity: 0,
transform: "translate(30px, 0)",
},
previous: {
opacity: 0,
transform: "translate(-30px, 0)",
},
};
Root Layout
I am Sub-page 1
Current route: {{src}}
Go to Page 2
I am Sub-page 2
Current route: {{src}}
Go to Page 1