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: [
    // الوثيقة: https://bootstrap-vue.js.org
    'bootstrap-vue/nuxt'،
    // الوثيقة: 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: {
    // جذر التطبيق URL
    base: '/nuxt-01/'
  },
  // الخادم
  server: {
    // منفذ الخدمة، 3000 افتراضيًا
    port: 81,
    // عناوين الشبكة المستمعة، افتراضيًا localhost: 127.0.0.1
    // 0.0.0.0 = جميع عناوين الشبكة الخاصة بالجهاز
    host: '0.0.0.0'
  }
}
  • السطر 62: يُشار إلى المجلد الذي يحتوي على كود المصدر للمشروع [dvp]؛
  • السطر 66: يتم تحديد جذر التطبيق [dvp] (يمكن إدخال ما تريد)؛
  • السطر 43: لاحظ أن المكتبة [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]، يقوم الكود بما يلي:

  • الأسطر 5-11: استخدام مكتبة [bootstrap-vue]. يتم تنفيذ هذه المهمة الآن بواسطة الوحدة النمطية [bootstrap-vue/nuxt] في السطر 43 من ملف التكوين [nuxt.config.js
  • السطور 14 و25: استخدام ملف التوجيه [router.js]. يتم تنفيذ هذه المهمة الآن تلقائيًا بواسطة التطبيق [nuxt] انطلاقًا من شجرة المجلد [pages
  • السطور 20-26: إنشاء مثيل للواجهة الرئيسية للتطبيق. في تطبيق [nuxt]، تُستخدم الواجهة [layouts/default.vue] كواجهة رئيسية؛

لم يعد للملف [main.js] أي سبب للوجود. لو كان له سبب، لتم الإعلان عنه في المفتاح [plugins] في السطر 30 من ملف التكوين [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>
  • في السطر 9، ضمن المشروع [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>

يستخدم هذا المكون لتنظيم صفحات التطبيق في عمودين:

  • السطور 7-9: العمود الأيسر على عمودين Bootstrap؛
  • الأسطر 11-13: العمود الأيمن على 10 أعمدة Bootstrap؛

[navigation.vue]


<template>
  <!-- قائمة Bootstrap ذات الخيارات الثلاثة -->
  <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] في الأسطر 4 و7 و10، يجب الاطلاع على المجلد [pages] [2]:

  • ستحتوي الصفحة [index] على URL [/]؛
  • الصفحة [page1] ستحتوي على URL و [/page1
  • الصفحة [page2] ستحتوي على URL [/page2

يمكن أيضًا كتابة المكون [navigation] بالطريقة التالية:


<template>
  <!-- قائمة Bootstrap ذات الخيارات الثلاثة -->
  <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, "عدد الحجج=", args.length)
  },
  created(...args) {
    console.log('[home created]', 'process.server=', process.server,
'process.client=', process.client, "عدد الحجج=", args.length)
  },
  beforeMount(...args) {
    console.log('[home beforeMount]', 'process.server=', process.server,
'process.client=', process.client, "عدد الحجج=", args.length)
  },
  mounted(...args) {
    console.log('[home mounted]', 'process.server=', process.server,
'process.client=', process.client, "عدد الحجج=", args.length)
  }
}
</script>
  • السطر 5: يتم وضع مكون التنقل في العمود الأيسر؛
  • الأسطر 7-9: يتم وضع تنبيه في العمود الأيمن؛

في الجزء <script>، نضع كودًا في وظائف دورة حياة الصفحة [beforeCreate, created, beforeMount, beforeMounted]. نريد معرفة أي منها يتم تنفيذه بواسطة الخادم []nuxt وأي منها بواسطة العميل [nuxt]. نذكر أمرين:

  • عندما يتم طلب صفحة إما عند بدء تشغيل التطبيق، كما في حالة الصفحة [index]، أو يدويًا من قبل المستخدم الذي يقوم بتحديث صفحة المتصفح أو يكتب عنوان URL يدويًا، يتم تسليمها أولاً بواسطة الخادم [nuxt]. يقوم هذا الخادم بتفسير الرمز أعلاه وتنفيذ جافا سكريبت الذي يحتوي عليه؛
  • عندما تصل الصفحة المرسلة من الخادم [nuxt] إلى المتصفح، فإنها تصل مع رمز العميل [nuxt]. يقوم هذا الأخير بتفسير الصفحة المذكورة أعلاه مرة أخرى؛
  • من خلال السجلات، نريد معرفة من يفعل ماذا لفهم هذه العملية بشكل أفضل؛
  • السطران 30-31: نستخدم في الدالة كائنًا عامًا [process] موجودًا على كل من الخادم والعميل:
    • [process.server] صحيح إذا تم تنفيذ الكود بواسطة الخادم، وخاطئ في حالة عدم التنفيذ؛
    • [process.client] يكون صحيحًا إذا تم تنفيذ الكود من قبل العميل، وخاطئًا في حالة عدم التنفيذ؛
    • نظرًا لأن المتغير [process] غير مُعلن في الكود، فنحن مضطرون إلى وضع السطر 14 لـ [eslint]. السطر [16] ضروري لأنه بخلاف ذلك، فإن [eslint] يعلن عن نوع آخر من الأخطاء بسبب المتغير [process]. أما السطر 15 فهو ضروري للسماح باستخدام [console] في وظائف دورة الحياة؛
  • السطر 29: نريد أيضًا معرفة ما إذا كانت وظائف دورة الحياة تتلقى معلمات. سنكتشف في الواقع أن [nuxt] تنقل معلومات إلى وظائف معينة. نريد معرفة ما إذا كانت وظائف دورة الحياة جزءًا منها؛
  • نكرر نفس الكود للأربع وظائف؛

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

وهو الذي يتحكم في تنفيذ المشروع [dvp]. وقد تم وصفه في الصفحة 33.

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 للصفحة المعروضة؛
  • الأسطر 57-67: هذا هو البرنامج النصي الذي عرض السجلات الموسومة بـ [Nuxt SSR]. تم إنتاج هذه السجلات من جانب الخادم وتم تضمين النتائج في برنامج نصي مضمن في الصفحة المرسلة؛
  • الأسطر 68-71: البرامج النصية التي تشكل العميل الذي يتم تنفيذه على جانب المتصفح؛

يتم تنفيذ البرامج النصية في الأسطر 68-71 وتحويل الصفحة المستلمة. لمعرفة الصفحة التي يتم عرضها في النهاية للمستخدم، يجب الانتقال إلى علامة التبويب [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>

تعليقات

  • للوهلة الأولى، تبدو الصفحة المعروضة في الأسطر 19-59 مماثلة للصفحة المستلمة؛
  • الأسطر 14-16: تظهر ثلاثة نصوص برمجية جديدة، واحدة لكل صفحة من صفحات التطبيق؛
  • الأسطر 76-79: تظهر أربعة [iframe

السطور 33 و37 و42، الروابط تسبب مشكلة. تبدو وكأنها روابط عادية، وعند النقر عليها ستقوم بإرسال طلب إلى الخادم. ولكن عند التنفيذ، نرى أن هذا ليس صحيحًا: لا يوجد طلب موجه إلى الخادم. لفهم السبب، يجب العودة إلى علامة التبويب [inspecteur] في المتصفح:

Image

نلاحظ أنه في [1, 2] تم ربط أحداث بالروابط. إن البرامج النصية في الأسطر 71-74 هي التي ربطت معالجات الأحداث بالروابط. وبالتالي:

  • الصفحة المعروضة من قبل العميل مطابقة بصريًا لتلك المرسلة من قبل الخادم؛
  • تمت إضافة سلوك ديناميكي إلى الصفحة من قبل العميل؛

الآن لنطلب الصفحة [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] (السطر 30). الأسطر 41-44، تم إرجاع كود العميل مع الصفحة. في النهاية، طلب URL يدويًا هو بمثابة إعادة تشغيل التطبيق. ببساطة، الصفحة المعروضة ليست بالضرورة الصفحة الرئيسية، بل هي الصفحة التي تم طلبها. بمجرد استلام الصفحة، يتولى العميل زمام الأمور. لن يتم طلب الخادم مرة أخرى ما لم يقرر المستخدم خلاف ذلك.