404 Not Found

404 Not Found


nginx

الصفحات والمسارات

أثناء إضافة صفحات تفاصيل المنتجات إلى MegaShop، قام Bob بإعداد 50 مسار vue-router يدويًا. في كل مرة يُضاف منتج جديد، كان عليه تعديل ملفات المسارات—كان ذلك مؤلمًا حقًا. أخبره Charlie أن Nuxt 3 يولّد المسارات تلقائيًا بناءً على اصطلاحات الملفات، لذا إنشاء ملف هو نفسه إنشاء مسار.

1. ما ستتعلمه


2. قصة حقيقية لمسؤول

(1) نقطة الألم: كابوس إعداد التوجيه اليدوي

أنشأ Bob 1,000 مسار لـ MegaShop باستخدام Vue Router التقليدي—واحد لكل فئة وكل صفحة منتج. في كل مرة يُضاف منتج جديد، كان عليه تعديل ملف المسار؛ وإذا فاته واحد، ظهرت أخطاء 404. لم تتمكن Alice من العثور على المنتجات، وارتفع معدل الشكاوى.

(2) حلول توجيه ملفات Nuxt

مع التوجيه القائم على الملفات في Nuxt 3، يحتاج Bob فقط لإنشاء ملف:

TEXT
pages/products/[id].vue  →  /products/:id

مليون منتج في ملف واحد، مع تمرير المعلمات الديناميكية تلقائيًا.

(3) الفوائد: توجيه بدون إعداد

لم يعد Bob بحاجة لكتابة إعدادات المسارات—إضافة صفحة جديدة بسيطة كإنشاء ملف جديد، ومليون صفحة تفاصيل منتجات تحتاج فقط ملف [id].vue واحد.


3. قواعد توجيه الملفات

(1) عملية تعيين المجلدات إلى المسارات

100%
flowchart LR
    A[pages/index.vue] -->|"/"| B[Root Route]
    C[pages/about.vue] -->|"/about"| C2[About Route]
    D[pages/products/index.vue] -->|"/products"| D2[Product List Route]
    E[pages/products/[id].vue] -->|"/products/:id"| E2[Product Detail Route]
    F[pages/categories/[...slug].vue] -->|"/categories/:slug*"| F2[Catch-all Route]

(2) قواعد تعيين توجيه الملفات

مسار الملف المسار المُولّد الوصف
pages/index.vue / الصفحة الرئيسية
pages/about.vue /about صفحة ثابتة
pages/products/index.vue /products قائمة المنتجات
pages/products/[id].vue /products/:id معلمة ديناميكية
pages/categories/[slug].vue /categories/:slug معلمات ديناميكية
pages/categories/[...slug].vue /categories/:slug(*) مسار شامل
pages/404.vue /404 404 مخصص

(1) ▶ مثال: توجيه الصفحات الأساسي

VUE
<!-- pages/index.vue -->
<template>
  <div>
    <h1>MegaShop - Millions of Products</h1>
    <NuxtLink to="/products">Browse Products</NuxtLink>
  </div>
</template>

الناتج:

TEXT
// Execution Successful
VUE
<!-- pages/about.vue -->
<template>
  <div>
    <h1>About MegaShop</h1>
    <p>Serving over 1 million products worldwide</p>
  </div>
</template>

4. التوجيه الديناميكي

(1) توجيه ديناميكي بمعلمة واحدة

استخدم صياغة [param] لتعريف معلمات التوجيه الديناميكية.

(1) ▶ مثال: توجيه ديناميكي لصفحات تفاصيل المنتجات

VUE
<!-- pages/products/[id].vue -->
<template>
  <div>
    <h1>Product #{{ route.params.id }}</h1>
    <p>Price: ${{ product?.price }} USD</p>
  </div>
</template>

<script setup lang="ts">
const route = useRoute()
const { data: product } = await useFetch(`/api/products/${route.params.id}`)
</script>

الناتج:

TEXT
// Execution Successful

(2) المسارات الشاملة

استخدم صياغة [...slug] لالتقاط مسارات متعددة المستويات.

(2) ▶ مثال: توجيه شامل لفئات متعددة المستويات

VUE
<!-- pages/categories/[...slug].vue -->
<template>
  <div>
    <h1>Category: {{ slugPath }}</h1>
    <p>{{ products.length }} products found</p>
  </div>
</template>

<script setup lang="ts">
const route = useRoute()
# /categories/electronics/headphones → slug = ['electronics', 'headphones']
const slugPath = computed(() => (route.params.slug as string[]).join('/'))
const { data: products } = await useFetch(`/api/categories/${slugPath.value}`)
</script>

الناتج:

TEXT
// Execution Successful

(3) أنواع معلمات التوجيه الديناميكية

الصياغة المطابقة مثال URL قيمة params
[id] قسم واحد /products/123 { id: '123' }
[id].vue + index.vue اختياري /products أو /products/123 { id?: '123' }
[...slug] شامل متعدد الأقسام /a/b/c { slug: ['a','b','c'] }

5. المسارات المتداخلة

(1) هيكل التوجيه المتداخل

يتطلب التوجيه المتداخل صفحة أب (ملف .vue بنفس الاسم) ومجلد فرعي يعملان معًا:

TEXT
pages/
├── products/
│   ├── index.vue          # /products (فرعي)
│   ├── [id].vue           # /products/:id (فرعي)
│   └── edit.vue           # /products/edit (فرعي)
└── products.vue           # /products (أب مع <NuxtPage />)

(1) ▶ مثال: مسارات متداخلة في صفحة المنتجات

VUE
<!-- pages/products.vue - تخطيط أب -->
<template>
  <div>
    <nav class="product-nav">
      <NuxtLink to="/products">All Products</NuxtLink>
      <NuxtLink to="/products/featured">Featured</NuxtLink>
    </nav>
    <!-- المسارات الفرعية تُعرض هنا -->
    <NuxtPage />
  </div>
</template>

الناتج:

TEXT
// Execution Successful
VUE
<!-- pages/products/index.vue - فرعي: قائمة المنتجات -->
<template>
  <div>
    <h1>All Products</h1>
    <p>1 million products available</p>
  </div>
</template>
VUE
<!-- pages/products/[id].vue - فرعي: تفاصيل المنتج -->
<template>
  <div>
    <h1>Product Detail</h1>
    <p>ID: {{ route.params.id }}</p>
  </div>
</template>

(2) مقارنة المسارات المتداخلة مقابل التخطيط

البُعد المسارات المتداخلة التخطيط
الآلية صفحة أب + فتحة NuxtPage layouts/ + NuxtLayout
علاقة التوجيه مسارات أب-فرعية تشترك في التخطيطات تبديل التخطيط على مستوى الصفحة
استرجاع البيانات كل من الأب والفرعي يستخدمان useFetch التخطيط لا يسترجع البيانات
حالات الاستخدام تسلسل فئة → منتج → مراجعة تخطيط الصفحة العام (رأس/تذييل)

6. التنقل البرمجي

(1) مقارنة ثلاث طرق للتنقل

API الغرض متاح على الخادم حالة الاستخدام
navigateTo() تنقل برمجي إعادة توجيه بعد تسجيل الدخول
useRouter().push() تنقل من جانب العميل تنقل بنقرة زر
NuxtLink روابط تعريفية تنقل في القوالب

(1) ▶ مثال: إعادة توجيه جانب الخادم بـ navigateTo

TYPESCRIPT
// في وسيط أو سياق جانب الخادم
export default defineNuxtRouteMiddleware((to) => {
  const isAuthenticated = useState('isAuthenticated')

  if (!isAuthenticated.value && to.path.startsWith('/admin')) {
    return navigateTo('/login', { redirectCode: 302 })
  }
})

الناتج:

TEXT
// Execution Successful

(2) ▶ مثال: تنقل جانب العميل بـ useRouter

VUE
<template>
  <button @click="goToProduct(product.id)">
    View Details
  </button>
</template>

<script setup lang="ts">
const router = useRouter()

function goToProduct(id: number) {
  router.push(`/products/${id}`)
}
</script>

الناتج:

TEXT
// Execution Successful

(3) ▶ مثال: استرجاع المعلمات بـ useRoute

VUE
<script setup lang="ts">
const route = useRoute()

# الوصول إلى المعلمات
const productId = route.params.id         # من [id].vue
const categorySlug = route.params.slug     # من [...slug].vue

# الوصول إلى معلمات الاستعلام
# /products?category=electronics&sort=price
const category = route.query.category      # 'electronics'
const sort = route.query.sort              # 'price'
</script>

الناتج:

TEXT
// Execution Successful

7. دليل عملي للتوجيه متعدد المستويات في MegaShop

(1) خطة توجيه MegaShop

URL الملف الوظيفة
/ pages/index.vue الصفحة الرئيسية
/products pages/products/index.vue قائمة المنتجات
/products/[id] pages/products/[id].vue تفاصيل المنتج
/categories/[category] pages/categories/[category].vue صفحة الفئة
/categories/[category]/[subcategory] pages/categories/[...slug].vue الفئة الفرعية
/cart pages/cart.vue سلة التسوق
/checkout pages/checkout.vue صفحة الدفع
/admin pages/admin/index.vue لوحة الإدارة
/admin/products pages/admin/products/index.vue إدارة المنتجات
/404 pages/404.vue صفحة 404

(1) ▶ مثال: صفحة 404 لـ MegaShop

VUE
<!-- pages/404.vue -->
<template>
  <div class="not-found">
    <h1>404 - Product Not Found</h1>
    <p>The product you're looking for doesn't exist.</p>
    <NuxtLink to="/products">Browse all products</NuxtLink>
  </div>
</template>

الناتج:

TEXT
// Execution Successful

8. مثال شامل: نظام توجيه MegaShop

VUE
<!-- pages/index.vue - الصفحة الرئيسية -->
<template>
  <div>
    <section class="hero">
      <h1>MegaShop</h1>
      <p>Over 1 million products, delivered worldwide</p>
      <NuxtLink to="/products">Shop Now</NuxtLink>
    </section>
    <section class="featured">
      <ProductCard v-for="p in featured" :key="p.id" :product="p" />
    </section>
  </div>
</template>

<script setup lang="ts">
const { data: featured } = await useFetch('/api/products/featured')
</script>
VUE
<!-- pages/products/[id].vue - تفاصيل المنتج -->
<template>
  <div v-if="product">
    <h1>{{ product.name }}</h1>
    <p class="price">${{ product.price }} USD</p>
    <button @click="addToCart">Add to Cart</button>
    <button @click="goBack">Back to List</button>
  </div>
  <div v-else>
    <p>Product not found</p>
    <NuxtLink to="/products">Browse Products</NuxtLink>
  </div>
</template>

<script setup lang="ts">
const route = useRoute()
const router = useRouter()
const { data: product } = await useFetch(`/api/products/${route.params.id}`)

function addToCart() {
  navigateTo('/cart')
}

function goBack() {
  router.back()
}
</script>

❓ أسئلة شائعة

س هل معلمات التوجيه الديناميكية هي نصوص أم أرقام؟
ج معلمات URL هي دائمًا نصوص. إذا كنت تحتاج أرقامًا، حوّلها يدويًا: Number(route.params.id)، أو دع نوع إرجاع API يحدد القيمة عند استخدام useFetch.
س ما الفرق بين [id].vue و [...slug].vue؟
ج [id] يطابق قسم مسار واحد فقط (/products/123)، بينما [...slug] يطابق مسارًا متعدد الأقسام (/a/b/c)، حيث slug هو مصفوفة. المسارات الشاملة مناسبة للفئات بعدد مستويات غير محدود.
س هل يجب أن تكون الصفحة الأب للمسار المتداخل موجودة؟
ج نعم، لا يتشكل المسار المتداخل إلا عند وجود كل من الصفحة الأب products.vue والمجلد الفرعي products/. إذا كنت تريد المسار الفرعي فقط، لا تنشئ الصفحة الأب.
س ما الفرق بين NuxtLink ووسم a العادي؟
ج NuxtLink يُستخدم للتنقل من جانب العميل (بدون تحديث الصفحة)، بينما وسم a يؤدي لتحديث كامل للصفحة. استخدم NuxtLink للتنقل الداخلي ووسم a للروابط الخارجية.
س كيف أنشئ صفحة 404 مخصصة؟
ج ببساطة أنشئ ملف pages/404.vue. يعرض Nuxt 3 هذه الصفحة تلقائيًا عندما لا يتطابق أي مسار مع الطلب. يمكنك أيضًا معالجتها في مسار شامل.
س ما العلاقة بين routeRules والمسارات؟
ج يُعدّ routeRules في nuxt.config.ts لتحديد استراتيجيات التصيير (SSR/ISR/CSR) بناءً على مسارات URL؛ لا تؤثر على تعريف المسارات. المسارات تُعرّف بملفات مجلد pages/؛ routeRules يتحكم فقط في سلوك التصيير.

📖ملخص


📝تمارين

  1. تمرين أساسي (الصعوبة: ⭐): أنشئ pages/about.vue و pages/contact.vue، وتحقق من توليد المسارات تلقائيًا.
  2. تمرين متقدم (الصعوبة: ⭐⭐): نفّذ توجيهًا ديناميكيًا ثنائي المستوى /products/[category]/[id] واعرض معلمتي "الفئة" و "id" على الصفحة.
  3. تحدٍ (الصعوبة: ⭐⭐⭐): نفّذ مسارًا شاملًا [...slug].vue يمكنه تصيير مسارات متعددة المستويات مثل /docs/getting-started/installation وعرض شريط تنقل تفصيلي.

---|

Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%