Skip to content

4. مثال [nuxt-01]: مسیریابی و ناوبری

ما قصد داریم مجموعه‌ای از مثال‌های ساده را برای بررسی گام به گام نحوه کار یک برنامه [nuxt] بسازیم. کار خود را با انتقال برنامه [vuejs-11] از مستندات «مقدمه به چارچوب VUE.JS با مثال» آغاز خواهیم کرد، تا ابتدا درک کنیم که ساختار کد یک برنامه [nuxt] چگونه با ساختار یک برنامه [vue] متفاوت است.

4.1. ساختار پروژه

پروژه [vuejs-11] پروژه‌ای بود که شامل ناوبری بین ویوها می‌شد:

Image

ساختار کد منبع پروژه [vuejs-11] به شرح زیر بود:

Image

  • [main.js] اسکریپتی بود که هنگام راه‌اندازی برنامه [vue] اجرا می‌شد؛
  • [router.js] قواعد مسیریابی را تعریف می‌کرد؛
  • [App.vue] نمای ساختاری برنامه بود. این نما چیدمان نماهای مختلف را سازماندهی می‌کرد؛
  • [Component1, Component2, Component3, Layout, Navigation] کامپوننت‌های مورد استفاده در نماهای مختلف برنامه بودند؛

هنگام انتقال برنامه [vue] [1] به یک برنامه [nuxt] [2]:

  • اسکریپت‌هایی که هنگام راه‌اندازی برنامه اجرا می‌شوند باید در کلید [plugins] فایل [nuxt.config.js] اعلام شوند. علاوه بر این، می‌توان اسکریپت‌های مربوط به سرور [nuxt] را از اسکریپت‌های مربوط به کلاینت [nuxt] جدا کرد؛
  • ویوی [App.vue] باید در پوشه [layouts] نصب و به [default.vue] تغییر نام داده شود؛
  • کامپوننت‌های [Component1, Component2, Component3] که اهداف مسیریابی هستند، باید به پوشه [pages] منتقل شوند. یکی از آن‌ها که به‌عنوان صفحه اصلی عمل می‌کند، باید به [index.vue] تغییر نام داده شود. در اینجا، ما فایل‌های زیر را تغییر نام داده‌ایم:
    • [Component1] --> [index]: متن [Home] را نمایش می‌دهد؛
    • [Component2] --> [page1]: متن [Page 1] را نمایش می‌دهد؛
    • [Component3] --> [page2]: متن [Page 2] را نمایش می‌دهد؛

[nuxt] از محتویات پوشه [pages] برای تولید پویا مسیرهای زیر استفاده می‌کند:

1
2
3
{ name :’index’, ‘path’ :’/’}
{ name :’page1’, ‘path’ :’/page1’}
{ name :’page2’, ‘path’ :’/page2’}

در نتیجه، فایل [router.js] که در پروژه [vue] استفاده می‌شود، دیگر در پروژه [nuxt] مورد نیاز نیست.

فایل پیکربندی [nuxt.config.js] به شرح زیر خواهد بود:


export default {
  mode: 'universal',
  /*
   ** Headers of the page
   */
  head: {
    title: 'Introduction à [nuxt.js]',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      {
        hid: 'description',
        name: 'description',
        content: 'ssr routing loading asyncdata middleware plugins store'
      }
    ],
    link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }]
  },
  /*
   ** Customize the progress-bar color
   */
  loading: { color: '#fff' },
  /*
   ** Global CSS
   */
  css: [],
  /*
   ** Plugins to load before mounting the App
   */
  plugins: [],
  /*
   ** Nuxt.js dev-modules
   */
  buildModules: [
    // سند: https://github.com/nuxt-community/eslint-module
    '@nuxtjs/eslint-module'
  ],
  /*
   ** Nuxt.js modules
   */
  modules: [
    // Doc: https://bootstrap-vue.js.org
    'bootstrap-vue/nuxt',
    // Doc: https://axios.nuxtjs.org/usage
    '@nuxtjs/axios'
  ],
  /*
   ** Axios module configuration
   ** See https://axios.nuxtjs.org/options
   */
  axios: {},
  /*
   ** Build configuration
   */
  build: {
    /*
     ** You can extend webpack config here
     */
    extend(config, ctx) {}
  },
  // پوشه کد منبع
  srcDir: 'nuxt-01',
  // روتر
  router: {
    // ریشهٔ برنامه
    base: '/nuxt-01/'
  },
  // سرور
  server: {
    // پورت سرویس، به‌طور پیش‌فرض 3000
    port: 81,
    // آدرس‌های شبکه‌ای که گوش داده می‌شوند، پیش‌فرض localhost: 127.0.0.1
    // 0.0.0.0 = تمام آدرس‌های شبکه روی دستگاه
    host: '0.0.0.0'
  }
}
  • خط ۶۲: پوشه‌ای را که حاوی کد منبع پروژه [dvp] است مشخص کنید؛
  • خط ۶۶: دایرکتوری ریشهٔ برنامهٔ [dvp] را مشخص کنید (می‌توانید هر مقداری که می‌خواهید وارد کنید)؛
  • خط ۴۳: توجه داشته باشید که کتابخانه [bootstrap-vue] در پیکربندی ارجاع داده شده است؛

4.2. انتقال فایل [main.js]

فایل [main.js] از پروژه [vuejs-11] به شرح زیر بود:


// واردات‌ها
import Vue from 'vue'
import App from './App.vue'

// افزونه‌ها
import BootstrapVue from 'bootstrap-vue'
Vue.use(BootstrapVue);

// بوت‌استرپ
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'

// روتر
import monRouteur from './router'

// پیکربندی
Vue.config.productionTip = false

// مصالحه پروژه [App]
new Vue({
  name: "app",
  // نمای اصلی
  render: h => h(App),
  // روتر
  router: monRouteur,
}).$mount('#app')

به جز [imports]، کد کارهای زیر را انجام می‌دهد:

  • خطوط ۵–۱۱: استفاده از کتابخانه [bootstrap-vue]. این کار اکنون توسط ماژول [bootstrap-vue/nuxt] در خط ۴۳ فایل پیکربندی [nuxt.config.js] انجام می‌شود؛
  • خطوط ۱۴ و ۲۵: استفاده از فایل مسیریابی [router.js]. این کار اکنون به طور خودکار توسط برنامه [nuxt] بر اساس ساختار دایرکتوری پوشه [pages] انجام می‌شود؛
  • خطوط ۲۰–۲۶: نمونه‌سازی نمای اصلی برنامه. در یک برنامه [nuxt]، نمای [layouts/default.vue] به‌عنوان نمای اصلی عمل می‌کند؛

فایل [main.js] دیگر مورد نیاز نیست. اگر مورد نیاز بود، در کلید [plugins] در خط ۳۰ فایل پیکربندی [nuxt.config.js] اعلام می‌شد؛

4.3. نما اصلی [default.vue]

Image

نمای اصلی [layouts / default.vue] به شرح زیر است:


<template>
  <div class="container">
    <b-card>
      <!-- یک پیام -->
      <b-alert show variant="success" align="center">
        <h4>[nuxt-01] : routage et navigation</h4>
      </b-alert>
      <!--نمای مسیریابی فعلی -->
      <nuxt />
    </b-card>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>
  • در خط ۹، در پروژه [vuejs-11]، از تگ <router-view /> به جای تگ <nuxt /> که در اینجا استفاده شده است، استفاده شده بود. به نظر می‌رسد هر دو کار می‌کنند. من هر دو را امتحان کردم اما هیچ تفاوتی مشاهده نکردم. من تگ <nuxt /> را که تگ پیشنهادی است، حفظ کرده‌ام. این تگ نمای فعلی را نمایش می‌دهد، یعنی صفحه مقصد مسیر فعلی؛

4.4. کامپوننت‌ها

Image

در مقایسه با پروژه [vuejs-11]، کامپوننت‌های [layout, navigation] بدون تغییر باقی می‌مانند:

[components / layout.vue]


<!-- چیدمان نما -->
<template>
  <!-- ردیف -->
  <div>
    <b-row>
      <!-- میدان دو ستونی -->
      <b-col v-if="left" cols="2">
        <slot name="left" />
      </b-col>
      <!-- منطقهٔ ده ستونی -->
      <b-col v-if="right" cols="10">
        <slot name="right" />
      </b-col>
    </b-row>
  </div>
</template>

<script>
export default {
  // تنظیمات
  props: {
    left: {
      type: Boolean
    },
    right: {
      type: Boolean
    }
  }
}
</script>

این کامپوننت برای ساختاردهی صفحات برنامه به دو ستون استفاده می‌شود:

  • خطوط ۷–۹: ستون سمت چپ که دو ستون بوت‌استرپ را در بر می‌گیرد؛
  • خطوط ۱۱–۱۳: ستون سمت راست، با عرض ۱۰ ستون بوت‌استرپ؛

[navigation.vue]


<template>
  <!-- منوی بوت‌استرپ با سه گزینه -->
  <b-nav vertical>
    <b-nav-item to="/" exact exact-active-class="active">
      Home
    </b-nav-item>
    <b-nav-item to="/page1" exact exact-active-class="active">
      Page 1
    </b-nav-item>
    <b-nav-item to="/page2" exact exact-active-class="active">
      Page 2
    </b-nav-item>
  </b-nav>
</template>

این کامپوننت سه لینک ناوبری را نمایش می‌دهد:

Image

برای اینکه بفهمید چه مقادیری را برای ویژگی‌های [to] در خطوط ۴، ۷ و ۱۰ باید تنظیم کنید، باید به پوشه [pages] [2] نگاه کنید:

  • صفحه [index] شامل URL و [/] خواهد بود؛
  • صفحه [page1] شامل URL و [/page1] خواهد بود؛
  • صفحه [page2] دارای URL و [/page2] خواهد بود؛

کامپوننت [navigation] را می‌توان به صورت زیر نیز نوشت:


<template>
  <!--منوی بوت‌استرپ با سه گزینه -->
  <b-nav vertical>
    <nuxt-link to="/" exact exact-active-class="active">
      Home
    </nuxt-link>
    <nuxt-link to="/page1" exact exact-active-class="active">
      Page 1
    </nuxt-link>
    <nuxt-link to="/page2" exact exact-active-class="active">
      Page 2
    </nuxt-link>
  </b-nav>
</template>

تگ <b-nav-item> با تگ <nuxt-link> که نشان‌دهنده یک لینک مسیریابی است، جایگزین می‌شود. در عمل، من تفاوت قابل‌توجهی مشاهده نکرده‌ام – چیزی که ترازو را به نفع یکی از این تگ‌ها سنگین کند.

4.5. صفحات

Image

صفحه [index.vue] نمای زیر را نمایش می‌دهد:

Image

کد صفحه به شرح زیر است:


<!-- صفحه اصلی -->
<template>
  <Layout :left="true" :right="true">
    <!-- ناوبری -->
    <Navigation slot="left" />
    <!-- پیام-->
    <b-alert slot="right" show variant="warning">
      Home
    </b-alert>
  </Layout>
</template>

<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: {
    Layout,
    Navigation
  },
  //چرخهٔ زندگی
  beforeCreate(...args) {
    console.log('[home beforeCreate]', 'process.server=', process.server,
'process.client=', process.client, "تعداد آرگومان‌ها=", QZXW2HTMLCYXJncy.sZW5ndGgZQX)
  },
  created(...args) {
    console.log('[home created]', 'process.server=', process.server,
'process.client=', process.client, "number of arguments=", QZXW2HTMLCYXJncy.sZW5ndGgZQX)
  },
  beforeMount(...args) {
    console.log('[home beforeMount]', 'process.server=', process.server,
'process.client=', process.client, "number of arguments=", QZXW2HTMLCYXJncy.sZW5ndGgZQX)
  },
  mounted(...args) {
    console.log('[home mounted]', 'process.server=', process.server,
'process.client=', process.client, "number of arguments=", args.length)
  }
}
</script>
  • خط ۵: کامپوننت ناوبری در ستون سمت چپ قرار داده شده است؛
  • خطوط ۷–۹: یک هشدار در ستون سمت راست قرار داده شده است؛

در بخش <script>، کد را درون توابع چرخهٔ عمر صفحه [beforeCreate, created, beforeMount, beforeMounted] قرار می‌دهیم. می‌خواهیم بدانیم کدام‌یک توسط سرور nuxt اجرا می‌شوند و کدام‌یک توسط کلاینت [nuxt]. بیایید دو نکته را یادآوری کنیم:

  • وقتی یک صفحه درخواست می‌شود، چه در زمان راه‌اندازی برنامه، مانند مورد صفحه [index]، یا به‌صورت دستی توسط کاربر با تازه‌سازی صفحه در مرورگر یا تایپ دستی آدرس URL، ابتدا توسط سرور [nuxt] ارائه می‌شود. سرور کد فوق را تفسیر کرده و جاوااسکریپت موجود در آن را اجرا می‌کند؛
  • وقتی صفحه‌ای که توسط سرور [nuxt] ارسال شده به مرورگر می‌رسد، با کد کلاینت [nuxt] همراه است. این کد سپس بار دیگر صفحه بالا را تفسیر می‌کند؛
  • ما از لاگ‌ها برای ردیابی اینکه چه کسی چه کاری انجام می‌دهد استفاده می‌کنیم تا این فرآیند را بهتر درک کنیم؛
  • خطوط ۳۰–۳۱: تابع از یک شیء جهانی [process] استفاده می‌کند که هم در سرور و هم در کلاینت وجود دارد:
    • [process.server] اگر کد توسط سرور اجرا شود، مقدار true و در غیر این صورت مقدار false دارد؛
    • [process.client] اگر کد توسط کلاینت اجرا شود، مقدار true و در غیر این صورت مقدار false دارد؛
    • از آنجا که متغیر [process] در کد تعریف نشده است، مجبوریم خط ۱۴ را برای [eslint] درج کنیم. خط [16] ضروری است، زیرا در غیر این صورت، [eslint] به دلیل متغیر [process] نوع متفاوتی از خطا را ایجاد می‌کند. آیا خط ۱۵ برای امکان استفاده از [console] در توابع چرخه عمر ضروری است؟
  • خط ۲۹: ما همچنین می‌خواهیم بدانیم که آیا توابع چرخهٔ عمر آرگومان دریافت می‌کنند یا خیر. در واقع متوجه خواهیم شد که [nuxt] اطلاعات را به برخی توابع منتقل می‌کند. می‌خواهیم بدانیم آیا توابع چرخهٔ عمر در میان آن‌ها هستند یا خیر؛
  • ما همان کد را برای هر چهار تابع تکرار می‌کنیم؛

4.6. فایل [nuxt.config.js]

این فایل اجرای پروژه [dvp] را کنترل می‌کند. در صفحه ۳۳ به آن اشاره شده است.

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

ما پروژه را اجرا می‌کنیم:

Image

صفحه نمایش‌داده‌شده به شرح زیر است:

Image

پس از نصب در مرورگر، برنامه [nuxt] به یک برنامه استاندارد [vue] تبدیل می‌شود. بنابراین ما در مورد رفتار سمت کلاینت برنامه [nuxt-01] اظهار نظر نخواهیم کرد. این موضوع قبلاً در پروژه [vuejs-11] در مستند «مقدمه بر چارچوب VUE.JS از طریق مثال‌ها» پوشش داده شده است.

برنامه [nuxt] تنها در دو جنبه با برنامه [vue] تفاوت دارد:

  • راه‌اندازی اولیهٔ برنامه که صفحهٔ اصلی را نمایش می‌دهد؛
  • هرگاه کاربر به هر نحوی دستور تازه‌سازی مرورگر را صادر کند؛

در هر دو مورد:

  • صفحهٔ درخواستی توسط سرور ارائه می‌شود؛
  • صفحه دریافت‌شده توسط کلاینت پردازش می‌شود؛

بیایید نگاهی به لاگ‌های راه‌اندازی برنامه بیندازیم (F12 در مرورگر):

Image

  • در [1]، لاگ‌های سرور (process.server=true). این لاگ‌ها با ورودی [Nuxt SSR] (SSR= Server Side Rendered) پیش‌روی می‌شوند؛
  • در [2]، لاگ‌های کلاینت در مرورگر (process.client=true);

از روی این لاگ‌ها می‌توان نتیجه گرفت که:

  • سرور توابع چرخه عمر [beforeCreate, created] را اجرا می‌کند؛
  • کلاینت توابع چرخه عمر [beforeCreate, created, beforeMount, mounted] را اجرا می‌کند؛
  • سرور صفحه را قبل از کلاینت پردازش کرد؛
  • در هر دو مورد، هیچ‌یک از توابع اجراشده هیچ آرگومانتی نمی‌گیرند؛

اکنون بیایید نگاهی به کد منبع صفحهٔ دریافت‌شده بیندازیم (گزینه [Code source de la page] در مرورگر):


<!doctype html>
<html data-n-head-ssr>
<head>
  <title>Introduction à [nuxt.js]</title>
  <meta data-n-head="ssr" charset="utf-8">
  <meta data-n-head="ssr" name="viewport" content="width=device-width, initial-scale=1">
  <meta data-n-head="ssr" data-hid="description" name="description" content="ssr routing loading asyncdata middleware plugins store">
  <link data-n-head="ssr" rel="icon" type="image/x-icon" href="/favicon.ico">
  <base href="/nuxt-01/">
  ....
  <link rel="preload" href="/nuxt-01/_nuxt/runtime.js" as="script">
  <link rel="preload" href="/nuxt-01/_nuxt/commons.app.js" as="script">
  <link rel="preload" href="/nuxt-01/_nuxt/vendors.app.js" as="script">
  <link rel="preload" href="/nuxt-01/_nuxt/app.js" as="script">
</head>
<body>
  <div data-server-rendered="true" id="__nuxt">
    <div id="__layout">
      <div class="container">
        <div class="card">
          <div class="card-body">
            <div role="alert" aria-live="polite" aria-atomic="true" align="center" class="alert alert-success">
              <h4>[nuxt-01] : routage et navigation</h4>
            </div>
            <div>
              <div class="row">
                <div class="col-2">
                  <ul class="nav flex-column">
                    <li class="nav-item">
                      <a href="/nuxt-01/" target="_self" class="nav-link active nuxt-link-active">
                        Home
                      </a>
                    </li>
                    <li class="nav-item">
                      <a href="/nuxt-01/page1" target="_self" class="nav-link">
                        Page 1
                      </a>
                    </li>
                    <li class="nav-item">
                      <a href="/nuxt-01/page2" target="_self" class="nav-link">
                        Page 2
                      </a>
                    </li>
                  </ul>
                </div> <div class="col-10">
                  <div role="alert" aria-live="polite" aria-atomic="true" class="alert alert-warning">
                    Home
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <script>
    window.__NUXT__ = (function (a, b, c, d, e, f, g, h, i, j) {
      return {
        layout: "default", data: [{}], error: null, serverRendered: true,
        logs: [
          { date: new Date(1574069600078), args: [a, b, c, d, e, f, g, "(repeated 1 times)"], type: h, level: i, tag: j },
          { date: new Date(1574070938091), args: [a, b, c, d, e, f, g], type: h, level: i, tag: j }
        ]
      }
    }("[home beforeCreate]", "process.server=", "true", "process.client=", "false", "nombre d'arguments=", "0", "log", 2, ""));
  </script>
  <script src="/nuxt-01/_nuxt/runtime.js" defer></script>
  <script src="/nuxt-01/_nuxt/commons.app.js" defer></script>
  <script src="/nuxt-01/_nuxt/vendors.app.js" defer></script>
  <script src="/nuxt-01/_nuxt/app.js" defer></script>
</body>
</html>

نظرات

  • اولین نکته‌ای که به چشم می‌آید این است که کد دریافت‌شده HTML به درستی آنچه کاربر می‌بیند را منعکس می‌کند. این موضوع در مورد برنامه‌های [vue] صدق نمی‌کرد، که در آن کد منبع نمایش‌داده‌شده، مربوط به یک فایل HTML تقریباً خالی بود. این چیزی بود که مرورگر دریافت کرده بود. سپس کلاینت [vue] کنترل را در دست گرفت و صفحه‌ای را که کاربر انتظار داشت ببیند، ساخت. سپس باید به زبانه [inspecteur] در ابزار توسعه‌دهنده مرورگر (F12) می‌رفتید تا کد HTML صفحه نمایش‌داده‌شده را مشاهده کنید؛
  • خطوط ۵۷–۶۷: این اسکریپتی است که لاگ‌های دارای برچسب [Nuxt SSR] را نمایش می‌دهد. این لاگ‌ها در سمت سرور تولید شده و نتایج در اسکریپتی که در صفحه ارسال‌شده گنجانده شده بود، جاسازی شده بودند؛
  • خطوط ۶۸–۷۱: اسکریپت‌هایی که کد سمت کلاینت را در مرورگر اجرا می‌کنند؛

اسکریپت‌های خطوط ۶۸–۷۱ اجرا شده و صفحه دریافت‌شده را تبدیل می‌کنند. برای مشاهده صفحه‌ای که در نهایت به کاربر نمایش داده می‌شود، به زبانه [inspecteur] در ابزار توسعه‌دهنده مرورگر (F12) بروید:

Image

وقتی تگ <html> ([3]) را گسترش می‌دهید، محتوای زیر را مشاهده خواهید کرد:


<head>
  <title>Introduction à [nuxt.js]</title>
  <meta data-n-head="ssr" charset="utf-8">
  <meta data-n-head="ssr" name="viewport" content="width=device-width, initial-scale=1">
  <meta data-n-head="ssr" data-hid="description" name="description" content="ssr routing loading asyncdata middleware plugins store">
  <link data-n-head="ssr" rel="icon" type="image/x-icon" href="/favicon.ico">
  <base href="/nuxt-01/">
  ...
  <link rel="preload" href="/nuxt-01/_nuxt/runtime.js" as="script">
  <link rel="preload" href="/nuxt-01/_nuxt/commons.app.js" as="script">
  <link rel="preload" href="/nuxt-01/_nuxt/vendors.app.js" as="script">
  <link rel="preload" href="/nuxt-01/_nuxt/app.js" as="script">

  <script charset="utf-8" src="/nuxt-01/_nuxt/pages_index.js"></script>
  <script charset="utf-8" src="/nuxt-01/_nuxt/pages_page1.js"></script>
  <script charset="utf-8" src="/nuxt-01/_nuxt/pages_page2.js"></script>
</head>
<body>
  <div id="__nuxt">
    <div id="__layout">
      <div class="container">
        <div class="card">
          <div class="card-body">
            <div role="alert" aria-live="polite" aria-atomic="true" class="alert alert-success" align="center">
              <h4>[nuxt-01] : routage et navigation</h4>
            </div>
            <div>
              <div class="row">
                <div class="col-2">
                  <ul class="nav flex-column">
                    <li class="nav-item">
                      <a href="/nuxt-01/" target="_self" class="nav-link active nuxt-link-active">
                        Home
                      </a>
                    </li>
                    <li class="nav-item">
                      <a href="/nuxt-01/page1" target="_self" class="nav-link">
                        Page 1
                      </a>
                    </li>
                    <li class="nav-item">
                      <a href="/nuxt-01/page2" target="_self" class="nav-link">
                        Page 2
                      </a>
                    </li>
                  </ul>
                </div>
                <div class="col-10">
                  <div role="alert" aria-live="polite" aria-atomic="true" class="alert alert-warning">
                    Home
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <script>
    window.__NUXT__ = (function (a, b, c, d, e, f, g, h, i) {
      return {
        layout: "default", data: [{}], error: null, serverRendered: true,
        logs: [
          { date: new Date(1574068674481), args: ["[home beforeCreate]", a, b, c, d, e, f], type: g, level: h, tag: i },
          { date: new Date(1574068674482), args: ["[home created]", a, b, c, d, e, f], type: g, level: h, tag: i }
        ]
      }
    }("process.server=", "true", "process.client=", "false", "nombre d'arguments=", "0", "log", 2, ""));
  </script>
  <script src="/nuxt-01/_nuxt/runtime.js" defer=""></script>
  <script src="/nuxt-01/_nuxt/commons.app.js" defer=""></script>
  <script src="/nuxt-01/_nuxt/vendors.app.js" defer=""></script>
  <script src="/nuxt-01/_nuxt/app.js" defer=""></script>

  <iframe id="mc-sidebar-container" ...></iframe>
  <iframe id="mc-topbar-container"...>  </iframe>
  <iframe id="mc-toast-container" ...></iframe>
  <iframe id="mc-download-overlay-container"...></iframe>
</body>

نظرات

  • در نگاه اول، صفحه‌ای که در خطوط ۱۹ تا ۵۹ نمایش داده شده، به نظر می‌رسد با صفحه دریافت‌شده یکسان باشد؛
  • خطوط 14–16: سه اسکریپت جدید ظاهر می‌شوند، یکی برای هر یک از صفحات برنامه؛
  • خطوط ۷۶–۷۹: چهار نمونه از [iframe] ظاهر می‌شوند؛

خطوط ۳۳، ۳۷ و ۴۲: لینک‌ها مشکل‌ساز هستند. به نظر می‌رسد لینک‌های عادی هستند که با کلیک، درخواستی به سرور ارسال می‌کنند. اما در عمل، می‌بینیم که این‌طور نیست: هیچ درخواستی به سرور ارسال نمی‌شود. برای فهمیدن دلیل این موضوع، باید به برگه [inspecteur] در مرورگر بازگردیم:

Image

می‌توانیم ببینیم که در [1, 2]، رویدادها به لینک‌ها متصل شده‌اند. اسکریپت‌های موجود در خطوط ۷۱ تا ۷۴ هستند که رسیدگی‌کننده‌های رویداد را به لینک‌ها متصل کرده‌اند. بنابراین:

  • صفحه‌ای که توسط کلاینت نمایش داده می‌شود از نظر بصری با صفحه‌ای که توسط سرور ارسال شده یکسان است؛
  • رفتار پویا توسط کلاینت به صفحه اضافه شده است؛

اکنون بیایید صفحه [page1] را با تایپ دستی URL به عنوان [http://192.168.1.128:81/nuxt-01/page1] درخواست کنیم. لاگ‌ها به شکل زیر درمی‌آیند:

Image

ما همان نتایج را برای صفحه [index]، اما برای [page1] دریافت می‌کنیم. کد منبع صفحه دریافت‌شده به شرح زیر است:


<body>
  <div data-server-rendered="true" id="__nuxt">
    <div id="__layout">
      <div class="container">
        <div class="card">
          <div class="card-body">
            <div role="alert" aria-live="polite" aria-atomic="true" align="center" class="alert alert-success"><h4>[nuxt-01] : routage et navigation</h4></div> <div>
              <div class="row">
                <div class="col-2">
                  <ul class="nav flex-column">
                    <li class="nav-item">
                      <a href="/nuxt-01/" target="_self" class="nav-link">
                        Home
                      </a>
                    </li>
                    <li class="nav-item">
                      <a href="/nuxt-01/page1" target="_self" class="nav-link active nuxt-link-active">
                        Page 1
                      </a>
                    </li>
                    <li class="nav-item">
                      <a href="/nuxt-01/page2" target="_self" class="nav-link">
                        Page 2
                      </a>
                    </li>
                  </ul>
                </div> <div class="col-10">
                  <div role="alert" aria-live="polite" aria-atomic="true" class="alert alert-primary">

                    Page 1
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <script>window.__NUXT__ = { layout: "default", data: [{}], error: null, serverRendered: true, logs: [{ date: new Date(1573917721122), args: ["[page1 beforeCreate]", "process.server=", "true", "process.client=", "false", "nombre d'arguments=", "0"], type: "log", level: 2, tag: "" }] };</script>
  <script src="/nuxt-01/_nuxt/runtime.js" defer></script>
  <script src="/nuxt-01/_nuxt/commons.app.js" defer></script>
  <script src="/nuxt-01/_nuxt/vendors.app.js" defer></script>
  <script src="/nuxt-01/_nuxt/app.js" defer></script>
</body>

ما همان نوع صفحه‌ای را دریافت می‌کنیم که صفحه [index] است، اما با هشداری از نمای [Page 1] (خط ۳۰). خطوط ۴۱–۴۴: کد کلاینت همراه با صفحه بازگردانده شده است. در نهایت، درخواست دستی یک URL با راه‌اندازی مجدد برنامه یکسان است. با این حال، صفحه نمایش داده شده لزوماً صفحه اصلی نیست؛ بلکه همان صفحه‌ای است که درخواست شده بود. پس از دریافت صفحه، کنترل به کلاینت واگذار می‌شود. تا زمانی که کاربر تصمیم دیگری نگیرد، مجدداً با سرور تماس گرفته نخواهد شد.