Skip to content

11. مثال [nuxt-08]: میانی مسیریابی

در این مثال، مفهوم میانی مسیریابی را معرفی می‌کنیم: اسکریپت‌هایی که هرگاه یک مسیر تغییر کند اجرا می‌شوند.

مثال [nuxt-08] در ابتدا با کلون کردن پروژه [nuxt-01] ایجاد می‌شود:

Image

میان‌افزار مسیریابی باید در پوشه‌ای به نام [middleware] [2] قرار گیرد. ممکن است ساختار مسیریابی دو سطحی وجود داشته باشد:

  • مسیر‌یابی اعمال‌شده بر هر ناوبری. این مورد سپس در فایل [nuxt.config.js] اعلام می‌شود؛
  • مسیر‌یابی اعمال‌شده بر یک صفحهٔ خاص، زمانی که آن صفحه هدف مسیر‌یابی است. این مسیر‌یابی سپس در داخل همان صفحهٔ مقصد اعلام می‌شود؛

11.1. مسیر‌یابی عمومی

فایل [middleware / routing.js] مسیریابی عمومی را مدیریت می‌کند. این فایل در فایل [nuxt.config.js] به شرح زیر اعلام شده است:


  router: {
    base: '/nuxt-08/',
    middleware: ['routing']
},

میان‌افزار مسیریابی عمومی یک ویژگی روتر است (خط ۱). ممکن است چندین مؤلفه میان‌افزار مسیریابی وجود داشته باشد. به همین دلیل، در خط ۳، مقدار ویژگی [middleware] یک آرایه است. می‌توانیم ببینیم که از هیچ مسیری برای مشخص کردن میان‌افزار استفاده نشده است. این میان‌افزار به طور خودکار در پوشه [middleware] پروژه جستجو خواهد شد؛

میان‌افزار [routing] به سادگی اطلاعات را در اینجا ثبت می‌کند:


/* eslint-disable no-undef */
/* eslint-disable no-console */
export default function(...args) {
  // چه کسی این کد را اجرا می‌کند؟
  console.log('[routing], process.server=', process.server, 'process.client=', process.client)
  const who = process.server ? 'server' : 'client'
  const routing = '[routing ' + who + ']'
  // تعداد آرگومان‌ها
  console.log(routing + ', il y a', args.length, 'argument(s)')

  // آرگومان اول
  const context = args[0]
  //کلیدهای زمینه
  dumpkeys(routing + ', context', context)
  // برنامه
  dumpkeys(routing + ', context.app', context.app)
  //مسیر
  dumpkeys(routing + ', context.route', context.route)
  console.log(routing + ', context.route=', context.route)
  // روتر
  dumpkeys(routing + ', context.app.router', context.app.router)
  // router.options.routes
  dumpkeys(routing + ', context.app.router.options.routes', context.app.router.options.routes)
  console.log(routing + ', context.app.router.options.routes=', context.app.router.options.routes)
}

function dumpkeys(message, object) {
  // فهرست کلیدها برای [object]
  const ligne = 'Liste des clés [' + message + ']'
  console.log(ligne)
  // فهرست کلیدها
  if (object) {
    console.log(Object.keys(object))
  }
}
  • خط ۳: می‌بینیم که میان‌افزار یک آرگومان دریافت می‌کند: زمینهٔ اجرای‌کننده (سرور یا کلاینت)؛
  • خطوط ۴–۲۵: ما ویژگی‌های اشیاء مختلف را نمایش می‌دهیم تا مشخص کنیم چه چیزی قابل استفاده است. خواهیم دید که زمینه middleware تقریباً با زمینه plugin یکسان است؛

11.2. مسیر‌یابی برای یک صفحهٔ خاص

ما می‌خواهیم کنترل کنیم که کاربران چگونه به صفحه [index] برسند. برای این کار، باید ویژگی [middleware] را به این صفحه [index] اضافه کنیم:


<script>
/* eslint-disable no-undef */
/* eslint-disable no-console */
/* eslint-disable nuxt/no-env-in-hooks */

import Navigation from '@/components/navigation'
import Layout from '@/components/layout'

export default {
  name: 'Home',
  // components used
  components: {
    Layout,
    Navigation
  },
  // چرخهٔ عمر
  beforeCreate() {
    // کلاینت و سرور
    console.log('[home beforeCreate]')
  },
  created() {
    // کلاینت و سرور
    console.log('[home created]')
  },
  beforeMount() {
    //فقط کلاینت
    console.log('[home beforeMount]')
  },
  mounted() {
    // فقط کلاینت
    console.log('[home mounted]')
  },
  //مسیریابی
  middleware: ['index-routing']
}
</script>
  • خط ۳۴: خاصیت [middleware] فهرستی از اسکریپت‌هایی را که هر زمان صفحه بعدی نمایش داده می‌شود، یعنی صفحه [index]، باید اجرا شوند، لیست می‌کند. مجدداً، این اسکریپت‌ها در پوشه [middleware] پروژه جستجو خواهند شد؛

میان‌افزار [index-routing] به شرح زیر است:


/*eslint-disable no-undef */
/*eslint-disable no-console */
export default function(...args) {
  //چه کسی این کد را اجرا می‌کند؟
  console.log('[index-routing], process.server=', process.server, 'process.client=', process.client)
  const who = process.server ? 'server' : 'client'
  const indexRouting = '[index-routing ' + who + ']'
  // تعداد آرگومان‌ها
  console.log(indexRouting + ', il y a', args.length, 'argument(s)')

  // آرگومان اول
  const context = args[0]
  // کلیدهای زمینه
  dumpkeys(indexRouting + ', context', context)
  // برنامه
  dumpkeys(indexRouting + ', context.app', context.app)
  //مسیر
  dumpkeys(indexRouting + ', context.route', context.route)
  console.log(indexRouting + ', context.route=', context.route)
  // روتر
  dumpkeys(indexRouting + ', context.app.router', context.app.router)
  // router.options.routes
  dumpkeys(indexRouting + ', context.app.router.options.routes', context.app.router.options.routes)
  console.log(indexRouting + ', context.app.router.options.routes=', context.app.router.options.routes)
  // از کجا آمده‌ایم؟
  if (context.from) {
    console.log('from=', context.from)
  }
}

function dumpkeys(message, object) {
  // فهرست کلیدها برای [object]
  const ligne = 'Liste des clés [' + message + ']'
  console.log(ligne)
  //فهرست کلیدها
  if (object) {
    console.log(Object.keys(object))
  }
}

کد [index-routing] با کد [routing] یکسان است و نتایج مشابهی تولید می‌کند. آنچه برای ما جالب است، مشاهده زمان اجرای این دو کامپوننت میانی است.

11.3. اجرای پروژه

ما پروژه را اجرا می‌کنیم. لاگ‌ها به شرح زیر است:

اسکریپت [routing] ابتدا توسط سرور اجرا می‌شود:

[routing], process.server= true process.client= false
[routing server], il y a 1 argument(s)
Liste des clés [[routing server], context]
[ 'isStatic',
  'isDev',
  'isHMR',
  'app',
  'payload',
  'error',
  'base',
  'env',
  'req',
  'res',
  'ssrContext',
  'redirect',
  'beforeNuxtRender',
  'route',
  'next',
  '_redirected',
  '_errored',
  'params',
  'query',
   '$axios' ]
Liste des clés [[routing server], context.app]
[ 'router',
  'nuxt',
  'head',
  'render',
  'data',
  'beforeCreate',
  'created',
  'mounted',
  'watch',
  'computed',
  'methods',
  'components',
  'context',
   '$axios' ]
Liste des clés [[routing server], context.route]
[ 'name',
  'meta',
  'path',
  'hash',
  'query',
  'params',
  'fullPath',
  'matched' ]
[routing server], context.route= { name: 'index',
  meta: [ {} ],
  path: '/',
  hash: '',
  query: {},
  params: {},
  fullPath: '/',
  matched:
   [ { path: '',
       regex: /^(?:\/(?=$))?$/i,
       components: [Object],
       instances: {},
       name: 'index',
       parent: undefined,
       matchAs: undefined,
       redirect: undefined,
       beforeEnter: undefined,
       meta: {},
       props: {} } ] }
Liste des clés [[routing server], context.app.router]
[ 'app',
  'apps',
  'options',
  'beforeHooks',
  'resolveHooks',
  'afterHooks',
  'matcher',
  'fallback',
  'mode',
  'history' ]
Liste des clés [[routing server], context.app.router.options.routes]
[ '0', '1', '2' ]
[routing server], context.app.router.options.routes= [ { path: '/page1',
    component: [Function: _61cefe10],
    name: 'page1' },
  { path: '/page2',
    component: [Function: _61dd1591],
    name: 'page2' },
  { path: '/', component: [Function: _00d5e140], name: 'index' } ]

این با آنچه با پلاگین‌ها به دست آوردیم مطابقت دارد.

  • خط ۱۵: خاصیت [redirect] اغلب در میان‌افزار (middleware) استفاده می‌شود: این خاصیت امکان تغییر هدف مسیریابی فعلی را فراهم می‌کند؛

سپس، از آنجا که صفحه‌ای که باید نمایش داده شود [index] است، سرور اسکریپت [index-routing] را اجرا می‌کند و لاگ‌های زیر را نمایش می‌دهد:

[index-routing], process.server= true process.client= false
[index-routing server], il y a 1 argument(s)
Liste des clés [[index-routing server], context]
[ 'isStatic',
  'isDev',
  'isHMR',
  'app',
  'payload',
  'error',
  'base',
  'env',
  'req',
  'res',
  'ssrContext',
  'redirect',
  'beforeNuxtRender',
  'route',
  'next',
  '_redirected',
  '_errored',
  'params',
  'query',
   '$axios' ]
Liste des clés [[index-routing server], context.app]
[ 'router',
  'nuxt',
  'head',
  'render',
  'data',
  'beforeCreate',
  'created',
  'mounted',
  'watch',
  'computed',
  'methods',
  'components',
  'context',
   '$axios' ]
Liste des clés [[index-routing server], context.route]
[ 'name',
  'meta',
  'path',
  'hash',
  'query',
  'params',
  'fullPath',
  'matched' ]
[index-routing server], context.route= { name: 'index',
  meta: [ {} ],
  path: '/',
  hash: '',
  query: {},
  params: {},
  fullPath: '/',
  matched:
   [ { path: '',
       regex: /^(?:\/(?=$))?$/i,
       components: [Object],
       instances: {},
       name: 'index',
       parent: undefined,
       matchAs: undefined,
       redirect: undefined,
       beforeEnter: undefined,
       meta: {},
       props: {} } ] }
Liste des clés [[index-routing server], context.app.router]
[ 'app',
  'apps',
  'options',
  'beforeHooks',
  'resolveHooks',
  'afterHooks',
  'matcher',
  'fallback',
  'mode',
  'history' ]
Liste des clés [[index-routing server], context.app.router.options.routes]
[ '0', '1', '2' ]
[index-routing server], context.app.router.options.routes= [ { path: '/page1',
    component: [Function: _61cefe10],
    name: 'page1' },
  { path: '/page2',
    component: [Function: _61dd1591],
    name: 'page2' },
  { path: '/', component: [Function: _00d5e140], name: 'index' } ]

نتایج حاصل از اسکریپت [index-routing] مشابه نتایجی است که از اسکریپت [routing] به دست آمده است.

پس از دریافت صفحه [index] توسط مرورگر کلاینت، اسکریپت‌های سمت کلاینت کنترل را در دست می‌گیرند. لاگ‌ها به شکل زیر درمی‌آیند:

1
2
3
4
[home beforeCreate]
[home created]
[home beforeMount]
[home mounted]

بنابراین می‌توانیم ببینیم که وقتی برنامه راه‌اندازی می‌شود، کلاینت هیچ میان‌افزاری را اجرا نمی‌کند. این بدان معناست که این اتفاق هر بار که کاربر فراخوانی به سرور را آغاز می‌کند، رخ خواهد داد. میان‌افزار تنها زمانی توسط کلاینت اجرا می‌شود که در داخل کلاینت پیمایش صورت گیرد. برای مثال، با استفاده از لینک [Page 1] به صفحه [page1] بروید (در حال حاضر ما روی صفحه [index] هستیم). سپس لاگ‌ها به شرح زیر خواهند بود:

[routing], process.server= false process.client= true
[routing client], il y a 1 argument(s)
Liste des clés [[routing client], context]
(18) ["isStatic", "isDev", "isHMR", "app", "payload", "error", "base", "env", "redirect", "nuxtState", "route", "next", "_redirected", "_errored", "params", "query", "$axios", "from"]
Liste des clés [[routing client], context.app]
(14) ["router", "nuxt", "head", "render", "data", "beforeCreate", "created", "mounted", "watch", "computed", "methods", "components", "context", "$axios"]
Liste des clés [[routing client], context.route]
(8) ["name", "meta", "path", "hash", "query", "params", "fullPath", "matched"]
[routing client], context.route= {name: "page1", meta: Array(1), path: "/page1", hash: "", query: {}, }
Liste des clés [[routing client], context.app.router]
(10) ["app", "apps", "options", "beforeHooks", "resolveHooks", "afterHooks", "matcher", "fallback", "mode", "history"]
Liste des clés [[routing client], context.app.router.options.routes]
(3) ["0", "1", "2"]
[routing client], context.app.router.options.routes= (3) [{}, {}, {}]0: {path: "/page1", name: "page1", component: ƒ}1: {path: "/page2", name: "page2", component: ƒ}2: {path: "/", name: "index", component: ƒ}length: 3__proto__: Array(0)
[page1 beforeCreate]
[page1 created]
[page1 beforeMount]
[page1 mounted]
  • خط ۲: میان‌افزار [routing] توسط کلاینت اجرا می‌شود؛
  • خط ۴: به خصوصیت [from] توجه کنید: این مسیری است که از آن آمده‌ایم؛
  • خط ۹: [context.route] مسیری است که به آن می‌رویم؛
  • خطوط ۱۵–۱۸: صفحه [page1] نمایش داده می‌شود؛

اکنون از طریق لینک [Home] به صفحه [index] بازگردیم. سپس لاگ‌ها به شرح زیر است:

[routing], process.server= false process.client= true
[routing client], il y a 1 argument(s)
Liste des clés [[routing client], context]
(18) ["isStatic", "isDev", "isHMR", "app", "payload", "error", "base", "env", "redirect", "nuxtState", "route", "next", "_redirected", "_errored", "params", "query", "$axios", "from"]
Liste des clés [[routing client], context.app]
(14) ["router", "nuxt", "head", "render", "data", "beforeCreate", "created", "mounted", "watch", "computed", "methods", "components", "context", "$axios"]
Liste des clés [[routing client], context.route]
(8) ["name", "meta", "path", "hash", "query", "params", "fullPath", "matched"]
[routing client], context.route= {name: "index", meta: Array(1), path: "/", hash: "", query: {}, }
Liste des clés [[routing client], context.app.router]
(10) ["app", "apps", "options", "beforeHooks", "resolveHooks", "afterHooks", "matcher", "fallback", "mode", "history"]
Liste des clés [[routing client], context.app.router.options.routes]
(3) ["0", "1", "2"]
[routing client], context.app.router.options.routes= (3) [{}, {}, {}]0: {path: "/page1", name: "page1", component: ƒ}1: {path: "/page2", name: "page2", component: ƒ}2: {path: "/", name: "index", component: ƒ}length: 3__proto__: Array(0)
[index-routing], process.server= false process.client= true
[index-routing client], il y a 1 argument(s)
Liste des clés [[index-routing client], context]
(18) ["isStatic", "isDev", "isHMR", "app", "payload", "error", "base", "env", "redirect", "nuxtState", "route", "next", "_redirected", "_errored", "params", "query", "$axios", "from"]
Liste des clés [[index-routing client], context.app]
(14) ["router", "nuxt", "head", "render", "data", "beforeCreate", "created", "mounted", "watch", "computed", "methods", "components", "context", "$axios"]
Liste des clés [[index-routing client], context.route]
(8) ["name", "meta", "path", "hash", "query", "params", "fullPath", "matched"]
[index-routing client], context.route= {name: "index", meta: Array(1), path: "/", hash: "", query: {}, }
Liste des clés [[index-routing client], context.app.router]
(10) ["app", "apps", "options", "beforeHooks", "resolveHooks", "afterHooks", "matcher", "fallback", "mode", "history"]
Liste des clés [[index-routing client], context.app.router.options.routes]
(3) ["0", "1", "2"]
[index-routing client], context.app.router.options.routes= (3) [{}, {}, {}]0: {path: "/page1", name: "page1", component: ƒ}1: {path: "/page2", name: "page2", component: ƒ}2: {path: "/", name: "index", component: ƒ}length: 3__proto__: Array(0)
from= {name: "page1", meta: Array(1), path: "/page1", hash: "", query: {}, }
[home beforeCreate]
[home created]
[home beforeMount]
[home mounted]
  • خطوط ۱–۱۵: کلاینت میدل‌ویر [routing] را اجرا می‌کند. این طبیعی است. این میدل‌ویر هر بار که مسیر تغییر می‌کند اجرا می‌شود؛
  • خطوط 16–29: کلاینت میدل‌ویر [index-routing] را اجرا می‌کند، زیرا:
    • [index] هدف مسیر فعلی است (به خط ۲۳ مراجعه کنید)؛
    • صفحه [index] یک میان‌افزار به نام [index-routing] تعریف کرده است؛

بنابراین می‌توانیم ببینیم که میانیاب مسیریابی عمومی قبل از میانیاب متصل به صفحات توسط کلاینت اجرا می‌شود.