Vue.js Nested Routing Masterclass
This challenge focuses on mastering nested routing in Vue.js with TypeScript. You will build a hierarchical navigation structure within a single page, allowing users to explore related content without full page reloads. This is a fundamental concept for building complex, Single Page Applications (SPAs) with Vue.
Problem Description
Your task is to create a Vue.js application that demonstrates nested routing. You will define a main "Dashboard" route that contains a navigation sidebar. Within this sidebar, clicking on different links should load distinct content components into a designated content area, all while maintaining the "Dashboard" layout.
Key Requirements:
- Setup Vue Router: Configure Vue Router to handle nested routes.
- Define Parent Route: Create a "Dashboard" route that acts as the parent for nested routes. This route should include a layout component with a sidebar and a main content area.
- Define Child Routes: Create at least two child routes under the "Dashboard" route (e.g., "Overview" and "Settings"). Each child route should render a specific component within the content area of the parent's layout.
- Navigation: Implement navigation links (e.g., using
<router-link>) within the sidebar of the "Dashboard" layout component to switch between the child routes. - TypeScript: Ensure all components, route definitions, and configurations are written in TypeScript.
- Dynamic Content Loading: The content area of the "Dashboard" layout should dynamically update based on the active child route.
Expected Behavior:
- When the application loads, the "Dashboard" route should be active, displaying its layout.
- The default child route (e.g., "Overview") should be rendered in the content area.
- Clicking a navigation link in the sidebar should update the content area with the corresponding child component.
- The URL in the browser's address bar should reflect the active nested route (e.g.,
/dashboard/overview).
Edge Cases to Consider:
- 404 Handling: Implement a fallback route for any invalid URLs.
- Initial Load: Ensure the correct default child route is loaded when the parent route is accessed.
Examples
Example 1: Basic Nested Structure
Input: A Vue application with the following route configuration:
const routes: Array<RouteRecordRaw> = [
{
path: '/dashboard',
component: () => import('./views/DashboardLayout.vue'), // Contains sidebar and <router-view>
children: [
{
path: 'overview', // Relative path
name: 'DashboardOverview',
component: () => import('./views/Overview.vue'),
},
{
path: 'settings', // Relative path
name: 'DashboardSettings',
component: () => import('./views/Settings.vue'),
},
],
},
// ... other routes like 404
];
Output:
- Navigating to
/dashboard/overviewdisplays theDashboardLayout.vuecomponent. TheOverview.vuecomponent is rendered within the<router-view>ofDashboardLayout.vue. The sidebar inDashboardLayout.vuehas an active link for "Overview". - Navigating to
/dashboard/settingsdisplays theDashboardLayout.vuecomponent. TheSettings.vuecomponent is rendered within the<router-view>ofDashboardLayout.vue. The sidebar inDashboardLayout.vuehas an active link for "Settings".
Explanation: The parent route /dashboard sets up the layout, and the children array defines routes that are rendered inside the parent's <router-view>. The path in the children array is relative to the parent's path.
Example 2: Default Child Route
Input: The same route configuration as Example 1, but with an empty path for one of the children:
const routes: Array<RouteRecordRaw> = [
{
path: '/dashboard',
component: () => import('./views/DashboardLayout.vue'),
children: [
{
path: '', // Default child route
name: 'DashboardDefault',
component: () => import('./views/DefaultDashboardContent.vue'),
},
{
path: 'settings',
name: 'DashboardSettings',
component: () => import('./views/Settings.vue'),
},
],
},
// ...
];
Output:
Navigating to /dashboard (without any further path segments) will render DashboardLayout.vue and DefaultDashboardContent.vue within its <router-view>.
Explanation: An empty path in a child route signifies that it's the default child route to be rendered when the parent route is matched and no other child path is specified.
Example 3: 404 Handling with Nested Routes
Input: Route configuration including a 404 handler:
const routes: Array<RouteRecordRaw> = [
{
path: '/dashboard',
component: () => import('./views/DashboardLayout.vue'),
children: [
{
path: 'overview',
name: 'DashboardOverview',
component: () => import('./views/Overview.vue'),
},
{
path: 'settings',
name: 'DashboardSettings',
component: () => import('./views/Settings.vue'),
},
],
},
{
path: '/:catchAll(.*)', // Wildcard for 404
name: 'NotFound',
component: () => import('./views/NotFound.vue'),
},
];
Output:
Navigating to /dashboard/unknown-page will render DashboardLayout.vue and then the NotFound.vue component within its <router-view>, as none of the child routes match unknown-page.
Explanation: The /:catchAll(.*) route acts as a catch-all. If the URL doesn't match any of the defined routes including nested ones, it falls back to the NotFound.vue component.
Constraints
- Vue Version: Vue 3.x
- Router Version: Vue Router 4.x
- TypeScript Strictness: All TypeScript code should adhere to strict mode.
- Component Structure: Use Single File Components (
.vuefiles) for all components. - Package Management: Assume standard npm/yarn installation of Vue and Vue Router.
Notes
- Remember to install the necessary packages:
npm install vue vue-router@4oryarn add vue vue-router@4. - Pay close attention to the
pathdefinition for child routes. They are relative to their parent. - The
<router-view>component is crucial for rendering nested route components. - Consider using
useRouteranduseRoutecomposables for programmatic navigation and accessing route information. - For the "Dashboard" layout, you can create a simple structure with placeholder divs for the sidebar and content area. The focus is on the routing mechanism.