Vue.js: Vue Router

آخر تحديث: 2026-08-26

Vue Router هو مدير التوجيه الرسمي لـ Vue — فهو يتيح لتطبيقك أحادي الصفحة (SPA) أن يحتوي على «صفحات» متعددة، بحيث يتوافق كل عنوان URL مع مكون معين. Vue Router 4 هو الإصدار المصمم خصيصًا لـ Vue 3، وهو يدعم واجهة برمجة التطبيقات (API) الخاصة بالتركيب (Composition API) بشكل كامل.

يُعد التعيين بين عناوين URL والمكونات جوهر عملية التوجيه في SPA. ويُعد إتقان استخدام Vue Router 4 مهارة أساسية لتطوير أي تطبيق Vue غير بسيط.

1. ما ستتعلمه



2. «كابوس 404» في التطبيق أحادي الصفحة

(1) المشكلة: 5 صفحات، 5 حالات تكرار في الكود

تضمنت واجهة الإدارة الخاصة بـ«أليس» 5 صفحات (الصفحة الرئيسية/المنتجات/الطلبات/المستخدمون/الإعدادات):

VUE
<!-- ❌ The "Broken" Version: Use v-if to switch 5 components -->
<template>
  <div>
    <button @click="currentPage = 'home'">Home</button>
    <button @click="currentPage = 'products'">Products</button>
    <button @click="currentPage = 'orders'">Orders</button>
    
    <div v-if="currentPage === 'home'"><HomePage /></div>
    <div v-else-if="currentPage === 'products'"><ProductsPage /></div>
    <div v-else-if="currentPage === 'orders'"><OrdersPage /></div>
    <div v-else>Page not found</div>
  </div>
</template>

4 أسئلة:

(2) حل Vue Router 4: 5 مسارات + 5 مكونات

JS
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  { path: '/', component: () => import('@/views/HomePage.vue') },
  { path: '/products', component: () => import('@/views/ProductsPage.vue') },
  { path: '/orders', component: () => import('@/views/OrdersPage.vue') },
  { path: '/users', component: () => import('@/views/UsersPage.vue') },
  { path: '/settings', component: () => import('@/views/SettingsPage.vue') }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router
VUE
<!-- App.vue -->
<template>
  <nav>
    <router-link to="/">Home</router-link>
    <router-link to="/products">Products</router-link>
    <router-link to="/orders">Orders</router-link>
  </nav>
  
  <!-- ✅ Key:router-view Render the component for the current route -->
  <router-view />
</template>

5 مسارات + عرض جهاز توجيه واحد = تطبيق SPA كامل. تتم مزامنة عناوين URL تلقائيًا، وتعمل أزرار «الأمام» و«الخلف» في المتصفح كما هو متوقع.

(3) الإيرادات

بعد استخدام Vue Router:



3. تهيئة المسار

(1) كود التهيئة الكامل

JS
// src/router/index.js
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'

// 1. Define Routes(Lazy Loading)
const routes = [
  { path: '/', component: () => import('@/views/HomePage.vue') },
  { path: '/products', component: () => import('@/views/ProductsPage.vue') }
]

// 2. Create router Examples
const router = createRouter({
  // history Mode: URL without # (Recommended)
  history: createWebHistory(),
  // hash Mode: URL with # (Compatibility with older browsers)
  // history: createWebHashHistory(),
  
  routes,
  
  // Scrolling Behavior:Scroll to the top when switching routes
  scrollBehavior(to, from, savedPosition) {
    return savedPosition || { top: 0 }
  }
})

export default router

(2) تسجيل ملف main.js

JS
// src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

const app = createApp(App)
app.use(router)  // Registration Routes
app.mount('#app')

(3) مقارنة بين النموذجين الرئيسيين للتاريخ

الجانب createWebHistory createWebHashHistory
تنسيق عنوان URL /products /#/products
تحسين محركات البحث (SEO) ✅ متوافق مع تحسين محركات البحث ❌ غير متوافق مع تحسين محركات البحث
تكوين الخادم مطلوب (try_files) غير مطلوب
التوافق مع المتصفحات IE10+ IE8+
التقييم ⭐⭐⭐⭐⭐ ⭐⭐


4. 5 أنواع من تكوينات التوجيه

(1) التوجيه الثابت

JS
const routes = [
  { path: '/', component: () => import('@/views/HomePage.vue') },
  { path: '/about', component: () => import('@/views/AboutPage.vue') },
  { path: '/contact', component: () => import('@/views/ContactPage.vue') }
]

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

JS
const routes = [
  // /products/123
  { 
    path: '/products/:id', 
    component: () => import('@/views/ProductDetailPage.vue') 
  },
  // /users/456/posts/789
  { 
    path: '/users/:userId/posts/:postId', 
    component: () => import('@/views/PostPage.vue') 
  },
  // Optional Parameters
  { 
    path: '/news/:category?', 
    component: () => import('@/views/NewsPage.vue') 
  }
]
VUE
<!-- ProductDetailPage.vue Receive Parameters -->
<script setup>
import { useRoute } from 'vue-router'

const route = useRoute()
console.log(route.params.id)  // '123'
</script>

(3) المسارات المتداخلة

JS
const routes = [
  {
    path: '/users',
    component: () => import('@/views/UsersPage.vue'),
    children: [
      {
        path: '',  // Default Subroute
        component: () => import('@/views/UsersListPage.vue')
      },
      {
        path: ':id',  // /users/123
        component: () => import('@/views/UserDetailPage.vue')
      }
    ]
  }
]
VUE
<!-- UsersPage.vue -->
<template>
  <div>
    <h1>Users</h1>
    <router-view />  <!-- Subnet Route Outbound -->
  </div>
</template>

(4) التوجيه المسمى

JS
const routes = [
  { 
    path: '/products/:id', 
    name: 'product-detail',  // Named Routing
    component: () => import('@/views/ProductDetailPage.vue') 
  }
]
VUE
<!-- Navigate via name, Avoid hard-coding URL -->
<router-link :to="{ name: 'product-detail', params: { id: 123 } }">
  Product 123
</router-link>

(5) رمز البدل 404

JS
const routes = [
  { path: '/', component: () => import('@/views/HomePage.vue') },
  // ... Other Routes
  {
    path: '/:pathMatch(.*)*',  // Match all undefined routes
    component: () => import('@/views/NotFoundPage.vue')
  }
]


5. 5 أنواع من أنظمة الملاحة

VUE
<template>
  <!-- String Path -->
  <router-link to="/products">Products</router-link>
  
  <!-- Named Routing(Recommendations) -->
  <router-link :to="{ name: 'products' }">Products</router-link>
  
  <!-- Dynamic Parameters -->
  <router-link :to="{ name: 'product-detail', params: { id: 123 } }">
    Product 123
  </router-link>
  
  <!-- Query Parameters -->
  <router-link :to="{ path: '/search', query: { q: 'vue' } }">
    Search
  </router-link>
</template>

(2) التنقل البرمجي (router.push)

JS
import { useRouter } from 'vue-router'

const router = useRouter()

function goToProduct(id) {
  router.push(`/products/${id}`)  // String
  // or
  router.push({ name: 'product-detail', params: { id } })  // Object
}

function goBack() {
  router.back()  // Back
}

function goForward() {
  router.forward()  // Forward
}

function replaceCurrent() {
  router.replace('/login')  // Replace(Leaving No Trace of History)
}

(3) 5 اختلافات بين "دفع" و"replace"

الطريقة السلوك السجل
router.دفع() الانتقال إلى صفحة جديدة حفظ هذه الصفحة (يمكن العودة إليها)
router.replace() استبدال الصفحة الحالية دون ترك أي أثر (لا يمكن الرجوع)
router.go(n) التقدم/التراجع n خطوات عرض السجل
router.back() تراجع خطوة إلى الوراء استكشف التاريخ
router.forward() خطوة إلى الأمام جولة عبر التاريخ

(4) مقارنة بين البرمجة الإجرائية والبرمجة التصريحية

السيناريو التوصية
ينقر المستخدم على الرابط رابط الموجه (تصريحي)
التنقل الذي يتم تشغيله بواسطة JS router.دفع (برمجياً)
إعادة التوجيه بعد إرسال النموذج router.دفع
إعادة التوجيه بعد تسجيل الدخول router.replace
إعادة التوجيه التلقائي 404 router.back


6. Route Guard (Navigation Guard)

(1) 3 أنواع من الحراس

JS
// 1. Global Frontline Guard(Most Commonly Used)
router.beforeEach((to, from, next) => {
  const isLoggedIn = !!localStorage.getItem('token')
  
  if (to.meta.requiresAuth && !isLoggedIn) {
    next('/login')  // Skip Login
  } else {
    next()  // Clearance
  }
})

// 2. Dedicated Route Guard
const routes = [
  {
    path: '/admin',
    component: () => import('@/views/AdminPage.vue'),
    beforeEnter: (to, from, next) => {
      if (isAdmin()) next()
      else next('/403')
    }
  }
]

// 3. In-Component Guard
// Within the component:beforeRouteEnter / beforeRouteUpdate / beforeRouteLeave

(2) مثال كامل لحماية تسجيل الدخول

JS
// router/index.js
router.beforeEach((to, from, next) => {
  const token = localStorage.getItem('token')
  const isLoggedIn = !!token
  
  // Pages that require login
  if (to.meta.requiresAuth && !isLoggedIn) {
    return next({ 
      name: 'login', 
      query: { redirect: to.fullPath }  // Redirect after logging in
    })
  }
  
  // Already logged in. Go to the login page.
  if (to.name === 'login' && isLoggedIn) {
    return next({ name: 'home' })
  }
  
  next()
})
▶ جرّب الكود
JS
// Routing meta Layout
const routes = [
  {
    path: '/dashboard',
    component: () => import('@/views/DashboardPage.vue'),
    meta: { requiresAuth: true }  // You must log in
  }
]


7. مثال كامل: نظام توجيه الخلفية للتجارة الإلكترونية

▶ مثال: 1. 5 أنواع من تكوينات التوجيه

JS
const routes = [
  // 1. Static Routing
  { path: '/', name: 'home', component: () => import('@/views/HomePage.vue') },
  
  // 2. Dynamic Routing
  { 
    path: '/products/:id', 
    name: 'product-detail',
    component: () => import('@/views/ProductDetailPage.vue') 
  },
  
  // 3. Nested Routes
  {
    path: '/admin',
    component: () => import('@/views/AdminLayout.vue'),
    meta: { requiresAuth: true },
    children: [
      { path: '', name: 'admin-dashboard', component: () => import('@/views/DashboardPage.vue') },
      { path: 'products', name: 'admin-products', component: () => import('@/views/AdminProductsPage.vue') },
      { path: 'orders', name: 'admin-orders', component: () => import('@/views/AdminOrdersPage.vue') }
    ]
  },
  
  // 4. Named Routing
  { 
    path: '/user/:userId', 
    name: 'user-profile',
    component: () => import('@/views/UserProfilePage.vue') 
  },
  
  // 5. 404
  { path: '/:pathMatch(.*)*', name: 'not-found', component: () => import('@/views/NotFoundPage.vue') }
]
▶ جرّب الكود

▶ مثال: 2. التحميل المؤجل للمسارات (التحميل حسب الطلب لـ 5 مكونات)

JS
const routes = [
  // ✅ Recommendations:News import
  { path: '/', component: () => import('@/views/HomePage.vue') },
  { path: '/products', component: () => import('@/views/ProductsPage.vue') }
]
▶ جرّب الكود

▶ مثال: 3. 5 أنواع من التنقل

VUE
<!-- 1. String Path -->
<router-link to="/products">Products</router-link>

<!-- 2. Named Routing(Recommendations)-->
<router-link :to="{ name: 'products' }">Products</router-link>

<!-- 3. Dynamic Parameters -->
<router-link :to="{ name: 'product-detail', params: { id: 123 } }">
  Product 123
</router-link>

<!-- 4. Query Parameters -->
<router-link :to="{ path: '/search', query: { q: 'vue' } }">
  Search
</router-link>

<!-- 5. Programmatic Navigation -->
<button @click="goToProduct(123)">Go to Product</button>
▶ جرّب الكود
JS
import { useRouter } from 'vue-router'
const router = useRouter()
function goToProduct(id) {
  router.push({ name: 'product-detail', params: { id } })
}

▶ مثال: 4. إكمال «Login Guard»

JS
router.beforeEach((to, from, next) => {
  const token = localStorage.getItem('token')
  const isLoggedIn = !!token
  
  if (to.meta.requiresAuth && !isLoggedIn) {
    return next({ name: 'login', query: { redirect: to.fullPath } })
  }
  
  if (to.name === 'login' && isLoggedIn) {
    return next({ name: 'home' })
  }
  
  next()
})
▶ جرّب الكود

▶ مثال: 5. مرجع سريع لـ 5 أخطاء شائعة

الخطأ الأعراض الحل
لا توجد طريقة عرض جهاز التوجيه لم يتم عرض الصفحة إضافة <router-view />
لا يتم تحميل المسارات بشكل مؤجل بطء تحميل الشاشة الأولى استخدم () => import() للاستيراد الديناميكي
Infinite Loop لا يمكن الخروج منع وظيفة next() من تشغيل beforeEach مرة أخرى
مسار متداخل بدون مخرج الصفحة الفرعية غير معروضة أضف <router-view /> إلى المكون الأصلي
404 الطريق غير موجود خطأ إضافة path: '/:pathMatch(.*)*'

▶ مثال: 6. 5 مقارنات رئيسية في الأداء

الوضع الشاشة الأولى التبديل قابل للتطبيق
الاستيراد الثابت بطيء سريع المشاريع الصغيرة
الاستيراد الديناميكي ⭐⭐⭐⭐⭐ بطيء عند التحميل الأول موصى به
التحميل المؤجل لمجموعات التوجيه ⭐⭐⭐⭐⭐ بطء في التحميل الأول المشاريع الكبيرة
التحميل المسبق ⭐⭐⭐⭐ سريع تجربة المستخدم أولاً
SSR ⭐⭐⭐⭐⭐ سريع Nuxt 3


❓ أسئلة شائعة

س أيهما يجب أن أختار، createWebHistory أم createWebHashHistory؟
ج createWebHistory (عناوين URL التي لا تحتوي على #، وهي ملائمة لتحسين محركات البحث) تتطلب تهيئة الخادم؛ أما createWebHashHistory (عناوين URL التي تحتوي على #) فهي متوافقة مع المتصفحات القديمة. يُنصح باستخدام createWebHistory في بيئات الإنتاج.
س كيف يتلقى التوجيه الديناميكي المعلمات؟
ج استخدم الرابط useRoute(): const route = useRoute(); route.params.id.
س ما الفرق بين router.push وrouter.replace؟
ج push يُضيف إلى سجل المتصفح (مما يسمح للمستخدمين بالرجوع إلى الخلف)، بينما replace يستبدل الصفحة الحالية (دون ترك أي أثر في السجل). استخدم replace بعد تسجيل الدخول (نظرًا لأن المستخدمين لا يمكنهم العودة إلى صفحة تسجيل الدخول).
س هل يمكن تشغيل برنامج حماية جهاز التوجيه بشكل غير متزامن؟
ج نعم. beforeEach(async (to, from, next) => { await checkAuth(); next() }). لكن يجب توخي الحذر لتجنب الحلقات اللانهائية.
س كيف يتم تنفيذ التوجيه المتداخل؟
ج قم بتكوين المسار الفرعي ضمن المسار الرئيسي باستخدام children: []، وأضف <router-view /> إلى قالب المكون الرئيسي باعتباره نقطة الخروج للمسار الفرعي.
س ما هي الاختلافات بين Vue Router 4 و Vue Router 3؟
ج يدعم Vue Router 4 واجهة برمجة التطبيقات (API) الخاصة بالتركيب (useRouter/useRoute)، ويوفر استدلالًا أقوى لأنواع TypeScript، كما تم تغيير معلمات حارس التنقل (to/from/next). يجب أن تستخدم مشاريع Vue 3 Vue Router 4.
س إلى أي مدى يساهم التحميل المؤجل في تحسين الأداء؟
ج يمكن أن يقلل من وقت تحميل الشاشة الأولى بنسبة تتراوح بين 50 و80٪ (من خلال عدم تحميل الصفحات التي لم تتم زيارتها). ويكون هذا التأثير ملحوظًا بشكل خاص في المشاريع الكبيرة (10 صفحات أو أكثر).
س كيف يمكنني استخدام حقول الميتا في حراس المسارات؟
ج أضف meta: { requiresAuth: true } إلى تكوين المسار، واستخدم to.meta.requiresAuth في الحارس. تُستخدم هذه الحقول للأذونات والعناوين ومسار التنقل وغير ذلك.

📖 ملخص


📝 تمارين

  1. أسئلة أساسية (مستوى الصعوبة: ⭐)

    تنفيذ تطبيق SPA بسيط متعدد الصفحات:

    • 3 صفحات: الصفحة الرئيسية / عن الموقع / الاتصال بنا
    • شريط التنقل العلوي + عرض الموجه السفلي
    • قم بتكوين جهاز التوجيه باستخدام vue-router
  2. مسائل متقدمة (مستوى الصعوبة: ⭐⭐)

    تنفيذ توجيه منتجات التجارة الإلكترونية:

    • /products صفحة القائمة
    • /products/:id صفحة التفاصيل (المعلمات الديناميكية)
    • /products/:id/edit تعديل الصفحة
    • معالجة الخطأ 404
  3. مسألة التحدي (مستوى الصعوبة: ⭐⭐⭐)

    تنفيذ نظام توجيه كامل للخدمات الخلفية للتجارة الإلكترونية:

    1. 10 صفحات أو أكثر (الصفحة الرئيسية/المنتجات/الطلبات/المستخدمون/الإعدادات/تسجيل الدخول/404، إلخ)
    2. المسارات المتداخلة (/admin/dashboard، /admin/products، إلخ)
    3. التحميل المؤجل للمسارات (تحميل أسرع للشاشة الأولى)
    4. قم بتسجيل الدخول بصفة حارس (إذا لم تكن قد سجلت الدخول بعد، فانتقل إلى /login؛ وإذا كنت قد سجلت الدخول بالفعل، فارجع إلى هذه الصفحة)
    5. تغطية شاملة لخمس طرق للملاحة
    6. التنقل البرمجي (انقر على الزر للتنقل)
    7. تكوين المسارات ذات الأنواع القوية في TypeScript
Web-Tutorial.com

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

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

100%