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] كان عرض هيكل التطبيق. كان ينظم تخطيط العروض المختلفة؛
  • [المكون 1، المكون 2، المكون 3، التخطيط، التنقل] هي المكونات التي استُخدمت في طرق العرض المختلفة للتطبيق؛

عند نقل تطبيق [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: [
    // Doc: 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) {}
  },
  // source code directory
  srcDir: 'nuxt-01',
  // router
  router: {
    // application URL root
    base: '/nuxt-01/'
  },
  // server
  server: {
    // service port, default 3000
    port: 81,
    // network addresses listened to, default localhost: 127.0.0.1
    // 0.0.0.0 = all the machine's network addresses
    host: '0.0.0.0'
  }
}
  • السطر 62: حدد المجلد الذي يحتوي على كود مصدر المشروع [dvp]؛
  • السطر 66: حدد عنوان URL الجذر لتطبيق [dvp] (يمكنك إدخال ما تريد)؛
  • السطر 43: لاحظ أن مكتبة [bootstrap-vue] مشار إليها في التكوين؛

4.2. نقل ملف [main.js]

كان ملف [main.js] لمشروع [vuejs-11] كما يلي:


// imports
import Vue from 'vue'
import App from './App.vue'
 
// plugins
import BootstrapVue from 'bootstrap-vue'
Vue.use(BootstrapVue);
 
// bootstrap
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
 
// routeur
import monRouteur from './router'
 
// configuration
Vue.config.productionTip = false
 
// instanciation projet [App]
new Vue({
  name: "app",
  // vue principale
  render: h => h(App),
  // routeur
  router: monRouteur,
}).$mount('#app')

بصرف النظر عن [الاستيرادات]، يقوم الكود بما يلي:

  • الأسطر 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>
      <!-- a message -->
      <b-alert show variant="success" align="center">
        <h4>[nuxt-01] : routage et navigation</h4>
      </b-alert>
      <!-- the current routing view -->
      <nuxt />
    </b-card>
  </div>
</template>
 
<script>
export default {
  name: 'App'
}
</script>
  • في السطر 9، في مشروع [vuejs-11]، استخدمنا علامة <router-view /> بدلاً من علامة <nuxt /> المستخدمة هنا. يبدو أن كلاهما يعمل. جربت كلاهما دون أن ألاحظ أي تغيير. احتفظت بعلامة <nuxt />، وهي العلامة الموصى بها. تعرض العرض الحالي، أي الصفحة المستهدفة للمسار الحالي؛

4.4. المكونات

Image

بالمقارنة مع مشروع [vuejs-11]، لم تتغير مكونات [التخطيط، التنقل]:

[components / layout.vue]


<!-- view layout -->
<template>
  <!-- line -->
  <div>
    <b-row>
      <!-- two-column zone -->
      <b-col v-if="left" cols="2">
        <slot name="left" />
      </b-col>
      <!-- ten-column zone -->
      <b-col v-if="right" cols="10">
        <slot name="right" />
      </b-col>
    </b-row>
  </div>
</template>
 
<script>
export default {
  // paramètres
  props: {
    left: {
      type: Boolean
    },
    right: {
      type: Boolean
    }
  }
}
</script>

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

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

[navigation.vue]


<template>
  <!-- bootstrap menu with three options -->
  <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 menu with three options -->
  <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

فيما يلي كود الصفحة:


<!-- page principale -->
<template>
  <Layout :left="true" :right="true">
    <!-- navigation -->
    <Navigation slot="left" />
    <!-- message-->
    <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 used
  components: {
    Layout,
    Navigation
  },
  // life cycle
  beforeCreate(...args) {
    console.log('[home beforeCreate]', 'process.server=', process.server,
 'process.client=', process.client, "nombre d'arguments=", args.length)
  },
  created(...args) {
    console.log('[home created]', 'process.server=', process.server,
 'process.client=', process.client, "nombre d'arguments=", args.length)
  },
  beforeMount(...args) {
    console.log('[home beforeMount]', 'process.server=', process.server,
 'process.client=', process.client, "nombre d'arguments=", args.length)
  },
  mounted(...args) {
    console.log('[home mounted]', 'process.server=', process.server,
 'process.client=', process.client, "nombre d'arguments=", args.length)
  }
}
</script>
  • السطر 5: يتم وضع مكون التنقل في العمود الأيسر؛
  • الأسطر 7–9: يتم وضع تنبيه في العمود الأيمن؛

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

  • عندما يتم طلب صفحة — إما عند بدء تشغيل التطبيق (كما هو الحال مع صفحة [index]) أو يدويًا من قبل المستخدم عن طريق تحديث صفحة المتصفح أو كتابة عنوان URL يدويًا — يتم تسليمها أولاً بواسطة خادم [nuxt]. يقوم الخادم بتفسير الكود أعلاه وتنفيذ JavaScript الذي يحتوي عليه؛
  • عندما تصل الصفحة المرسلة من خادم [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
  • قام الخادم بمعالجة الصفحة قبل العميل؛
  • في كلتا الحالتين، لا تتلقى أي من الوظائف المنفذة أي معلمات؛

الآن دعونا نلقي نظرة على شفرة المصدر للصفحة المستلمة (خيار [Page Source] في المتصفح):


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

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

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 يدويًا هو نفس إعادة تشغيل التطبيق. الفرق الوحيد هو أن الصفحة المعروضة ليست بالضرورة الصفحة الرئيسية؛ بل هي الصفحة التي تم طلبها. بمجرد استلام الصفحة، يتولى العميل زمام الأمور. لن يتم الاتصال بالخادم بعد ذلك ما لم يقرر المستخدم خلاف ذلك.