frontend-routing

安装量: 129
排名: #6670

安装

npx skills add https://github.com/aj-geddes/useful-ai-prompts --skill frontend-routing

Frontend Routing Overview

Implement client-side routing with navigation, lazy loading, protected routes, and state management for multi-page single-page applications.

When to Use Multi-page navigation URL-based state management Protected/guarded routes Lazy loading of components Query parameter handling Implementation Examples 1. React Router v6 // App.tsx import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'; import { Layout } from './components/Layout'; import { Home } from './pages/Home'; import { NotFound } from './pages/NotFound'; import { useAuth } from './hooks/useAuth'; import React from 'react';

// Lazy loaded components const Dashboard = React.lazy(() => import('./pages/Dashboard')); const UserProfile = React.lazy(() => import('./pages/UserProfile')); const Settings = React.lazy(() => import('./pages/Settings'));

// Protected route wrapper const ProtectedRoute: React.FC<{ children: React.ReactNode }> = ({ children }) => { const { isAuthenticated } = useAuth();

if (!isAuthenticated) { return ; }

return <>{children}</>; };

export const App: React.FC = () => { return ( }> } />

      <Route
        path="dashboard"
        element={
          <ProtectedRoute>
            <React.Suspense fallback={<div>Loading...</div>}>
              <Dashboard />
            </React.Suspense>
          </ProtectedRoute>
        }
      />

      <Route
        path="users/:id"
        element={
          <React.Suspense fallback={<div>Loading...</div>}>
            <UserProfile />
          </React.Suspense>
        }
      />

      <Route path="settings" element={<Settings />} />
      <Route path="*" element={<NotFound />} />
    </Route>
  </Routes>
</BrowserRouter>

); };

// Usage in components import { useParams, useNavigate, useSearchParams } from 'react-router-dom';

const UserProfile: React.FC = () => { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); const [searchParams] = useSearchParams();

const tab = searchParams.get('tab') || 'profile';

return (

User {id}

Tab: {tab}

); };

  1. Vue Router 4 // router/index.ts import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'; import { useAuthStore } from '@/stores/auth';

const routes: RouteRecordRaw[] = [ { path: '/', component: () => import('@/views/Home.vue'), meta: { title: 'Home' } }, { path: '/login', component: () => import('@/views/Login.vue'), meta: { title: 'Login', requiresGuest: true } }, { path: '/dashboard', component: () => import('@/views/Dashboard.vue'), meta: { title: 'Dashboard', requiresAuth: true }, children: [ { path: 'users', component: () => import('@/views/Users.vue'), meta: { title: 'Users' } }, { path: 'analytics', component: () => import('@/views/Analytics.vue'), meta: { title: 'Analytics' } } ] }, { path: '/users/:id', component: () => import('@/views/UserDetail.vue'), meta: { title: 'User Details', requiresAuth: true } }, { path: '/:pathMatch(.)', component: () => import('@/views/NotFound.vue'), meta: { title: 'Not Found' } } ];

const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes });

// Navigation guards router.beforeEach((to, from, next) => { const authStore = useAuthStore();

// Update page title document.title = (to.meta.title as string) || 'App';

// Check authentication if (to.meta.requiresAuth && !authStore.isAuthenticated) { next('/login'); } else if (to.meta.requiresGuest && authStore.isAuthenticated) { next('/dashboard'); } else { next(); } });

export default router;

// main.ts import { createApp } from 'vue'; import App from './App.vue'; import router from './router';

createApp(App).use(router).mount('#app');

  1. Angular Routing // app-routing.module.ts import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { DashboardComponent } from './components/dashboard/dashboard.component'; import { AuthGuard } from './guards/auth.guard'; import { GuestGuard } from './guards/guest.guard';

const routes: Routes = [ { path: '', redirectTo: '/home', pathMatch: 'full' }, { path: 'home', loadComponent: () => import('./pages/home/home.component').then(m => m.HomeComponent) }, { path: 'login', loadComponent: () => import('./pages/login/login.component').then(m => m.LoginComponent), canActivate: [GuestGuard] }, { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard], children: [ { path: 'users', loadChildren: () => import('./features/users/users.module').then(m => m.UsersModule) } ] }, { path: 'users/:id', loadComponent: () => import('./pages/user-detail/user-detail.component') .then(m => m.UserDetailComponent), canActivate: [AuthGuard] }, { path: '**', redirectTo: '/home' } ];

@NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule {}

// auth.guard.ts import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router'; import { AuthService } from '../services/auth.service';

@Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate { constructor( private authService: AuthService, private router: Router ) {}

canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): boolean { if (this.authService.isAuthenticated()) { return true; }

this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
return false;

} }

// Component usage import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router';

@Component({ selector: 'app-user-detail', templateUrl: './user-detail.component.html' }) export class UserDetailComponent implements OnInit { userId: string | null = null; tab: string = 'profile';

constructor( private route: ActivatedRoute, private router: Router ) {}

ngOnInit(): void { this.route.params.subscribe(params => { this.userId = params['id']; });

this.route.queryParams.subscribe(params => {
  this.tab = params['tab'] || 'profile';
});

}

goHome(): void { this.router.navigate(['/']); }

navigateToTab(tab: string): void { this.router.navigate([], { relativeTo: this.route, queryParams: { tab }, queryParamsHandling: 'merge' }); } }

  1. Query Parameter Handling // React Hook for Query Params import { useSearchParams } from 'react-router-dom';

const SearchUsers: React.FC = () => { const [searchParams, setSearchParams] = useSearchParams();

const handleSearch = (query: string) => { setSearchParams({ q: query, page: '1' }); };

const query = searchParams.get('q') || ''; const page = searchParams.get('page') || '1';

return (

handleSearch(e.target.value)} placeholder="Search..." />

Results for: {query} (Page {page})

); };

// Vue Query Param Hook import { useRoute, useRouter } from 'vue-router'; import { computed } from 'vue';

export function useQueryParams() { const route = useRoute(); const router = useRouter();

const query = computed(() => route.query.q as string || ''); const page = computed(() => parseInt(route.query.page as string) || 1);

const setQuery = (q: string) => { router.push({ query: { q, page: '1' } }); };

return { query, page, setQuery }; }

  1. Route Transition Effects / CSS Transition / .fade-enter-active, .fade-leave-active { transition: opacity 0.3s ease; }

.fade-enter-from, .fade-leave-to { opacity: 0; }

.slide-enter-active, .slide-leave-active { transition: transform 0.3s ease; }

.slide-enter-from { transform: translateX(-100%); }

.slide-leave-to { transform: translateX(100%); }

Best Practices Use lazy loading for code splitting Implement route guards for protection Handle 404 routes appropriately Preserve scroll position Use query parameters for filters Implement breadcrumb navigation Manage route transitions smoothly Use named routes for maintainability Resources React Router Documentation Vue Router Guide Angular Routing Browser History API

返回排行榜