Skip to content

10. المثال [nuxt-07]: سياقات العميل والخادم

10.1. مقدمة

يهدف المثال [nuxt-07] إلى استكشاف كائن [context] على كل من جانب الخادم وجانب العميل. من المهم تذكر أن هذين المكونين لتطبيقات [nuxt] منفصلان: لا يشتركان في أي شيء باستثناء:

  • ما يختار الخادم إرساله إلى العميل (في استجابة HTTP والصفحة المعروضة)؛
  • ما يختار العميل إرساله إلى الخادم (في طلب HTTP الخاص به)؛

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

يتم الحصول على المثال [nuxt-07] في البداية عن طريق نسخ المثال [nuxt-01]:

Image

  • في [2]، سنضيف مكونًا إضافيًا مشتركًا بين العميل والخادم؛
  • في [3]، سنقوم بتعديل صفحة [index] بشكل طفيف؛

10.2. المكوّن الإضافي [common / main.js]

يتم تنفيذ المكون الإضافي [common / main.js] من قبل كل من العميل والخادم: ويرجع ذلك إلى التكوين التالي في [nuxt.config.js]:


/*
   ** Plugins to load before mounting the App
   */
plugins: [{ src: '~/plugins/common/main.js' }],
  • السطر 4: عدم وجود الخاصية [mode] يعني أن المكون الإضافي [~/plugins/common/main.js] سيتم تنفيذه من قبل كل من العميل والخادم: الخادم أولاً، ثم العميل؛

سيكون هذا المكون الإضافي كما يلي:


/* eslint-disable no-undef */
/* eslint-disable no-console */
export default function(...args) {
  // who executes this code?
  console.log('[main server], process.server=', process.server, 'process.client=', process.client)
  const who = process.server ? 'server' : 'client'
  const main = '[main ' + who + ']'
  // number of arguments
  console.log(main + ', il y a', args.length, 'arguments')
 
  // 1st argument
  const context = args[0]
  // key context
  dumpkeys(main + ', context', context)
  // the application
  dumpkeys(main + ', context.app', context.app)
  // the road
  dumpkeys(main + ', context.route', context.route)
  console.log(main + ', context.route=', context.route)
  // the router
  dumpkeys(main + ', context.app.router', context.app.router)
  // on router.options.routes
  dumpkeys(main + ', context.app.router.options.routes', context.app.router.options.routes)
  console.log(main + ', context.app.router.options.routes=', context.app.router.options.routes)
 
  // 2nd argument
  const inject = args[1]
  console.log('inject=', typeof inject)
}
 
function dumpkeys(message, object) {
  // list of [object] keys
  const ligne = 'Liste des clés [' + message + ']'
  console.log(ligne)
  // kEY LIST
  if (object) {
    console.log(Object.keys(object))
  }
}
  • الأسطر 31–39: تُدرج الدالة [dumpkeys] خصائص الكائن الذي تم تمريره كمعلمة ثانية. تسبق هذه القائمة الرسالة التي تم تمريرها كمعلمة أولى؛
  • السطر 3: نريد معرفة عدد الحجج التي تتلقاها الدالة. للقيام بذلك، نستخدم صيغة [...args]، التي ستضع معلمات الدالة الفعلية في المصفوفة [args]. سنجد أن هناك حجتين؛
  • السطر 5: نعرض من يقوم بتنفيذ الكود، الخادم أم العميل؛
  • السطر 6: منفذ الكود، العميل أو الخادم؛
  • السطر 7: ثابت سلسلة يستخدم في السجلات؛
  • السطر 12: سنرى أن الحجة الأولى التي يتلقاها المكون الإضافي هي سياق المنفذ؛
  • السطر 14: قائمة مفاتيح كائن [context
  • السطر 16: سنرى أن كائن [context] يحتوي على خاصية [app] تمثل تطبيق [nuxt
  • السطر 18: سنرى أن الكائن [context] يحتوي على خاصية [route] تمثل المسار الحالي للموجه؛
  • السطر 21: سنجد أن الكائن [app] يحتوي على خاصية [router] تمثل جهاز التوجيه؛
  • السطر 23: يمثل الكائن [router.options.routes] المسارات المختلفة للتطبيق؛
  • السطران 27-28: الحجة الثانية للمكوّن الإضافي هي الدالة [inject] التي استخدمناها في المثال [nuxt-06

10.3. المكوّن الإضافي الذي ينفذه الخادم

عند التشغيل، يعرض الخادم ما يلي:

[main server], process.server= true process.client= false
[main server], il y a 2 arguments
Liste des clés [[main server], context]
[
  'isStatic',
  'isDev',
  'isHMR',
  'app',
  'payload',
  'error',
  'base',
  'env',
  'req',
  'res',
  'ssrContext',
  'redirect',
  'beforeNuxtRender',
  'route',
  'next',
  '_redirected',
  '_errored',
  'params',
  'query',
  '$axios'
]
  • السطران 11–12: سبق لنا أن استخدمنا الخصائص [base] و [env]، التي تأتي قيمها من ملف [nuxt.config.js
  • السطر 8: تشير الخاصية [app] إلى تطبيق [nuxt
  • السطر 18: تشير الخاصية [route] إلى المسار الحالي للموجه، أي الصفحة التي سيرسلها الخادم؛
  • السطر 13: طلب HTTP من متصفح العميل؛
  • السطر 14: استجابة HTTP من الخادم؛

قائمة خصائص [context.app] هي كما يلي:

Liste des clés [[main server], context.app]
[
  'router',
  'nuxt',
  'head',
  'render',
  'data',
  'beforeCreate',
  'created',
  'mounted',
  'watch',
  'computed',
  'methods',
  'components',
  'context',
  '$axios'
]
  • السطر 3: تتيح لنا الخاصية [router] الوصول إلى موجه التطبيق. وهذا أمر مهم في [Nuxt] لأن الموجه يتم تعريفه بواسطة [Nuxt] نفسها وليس بواسطة المطور. تتيح هذه الخاصية للمطور إمكانية تعديل الموجه؛

قائمة خصائص [context.route] هي كما يلي:

Liste des clés [[main server], context.route]
[
  'name',
  'meta',
  'path',
  'hash',
  'query',
  'params',
  'fullPath',
  'matched'
]

المسار [context.route] عند بدء تشغيل الخادم هو كما يلي:

[main 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: {}
    }
  ]
}
  • السطر 2: نرى أن الصفحة التالية على الخادم هي [index] وأن مسارها هو [/] (السطر 10)؛
  • السطر 22: تسمح لك الخاصية [meta] بإضافة خصائص إلى المسارات؛

خصائص [context.app.router] الخاصة بالخادم هي كما يلي:

Liste des clés [[main server], context.app.router]
[
  'app',
  'apps',
  'options',
  'beforeHooks',
  'resolveHooks',
  'afterHooks',
  'matcher',
  'fallback',
  'mode',
  'history'
]

توجد المسارات المختلفة للتطبيق في الخاصية [context.app.router.options.routes]:

Liste des clés [[main server], context.app.router.options.routes]
[
  '0',
  '1',
  '2'
]
[main server], context.app.router.options.routes= [
  {
    path: '/page1',
    component: [Function: _d7b6c762],
    name: 'page1'
  },
  {
    path: '/page2',
    component: [Function: _d79a9860],
    name: 'page2'
  },
  {
    path: '/',
    component: [Function: _31eaad9f],
    name: 'index'
  }
]

وأخيرًا، الحجة الثانية:

inject= function

10.4. صفحة [index] الخاصة بالخادم

صفحة [index] هي كما يلي:


<!-- 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
  },
  data() {
    return {
      who: process.server ? 'server' : 'client'
    }
  },
 
  // life cycle
  beforeCreate() {
    // client and server
    console.log('[home beforeCreate]')
  },
  created() {
    // client and server
    console.log('[home ' + this.who + ' created]')
    this.dumpkeys('[home ' + this.who + ' created], this.$nuxt', this.$nuxt)
    this.dumpkeys('[home ' + this.who + ' created], this.$nuxt.context', this.$nuxt.context)
  },
  beforeMount() {
    // customer only
    console.log('[home ' + this.who + ' beforeMount]')
  },
  mounted() {
    // customer only
    console.log('[home ' + this.who + ' mounted]')
  },
  methods: {
    dumpkeys(message, object) {
      // list of [object] keys
      const ligne = 'Liste des clés [' + message + ']'
      console.log(ligne)
      if (object) {
        console.log(Object.keys(object))
      }
    }
  }
}
</script>
  • السطر 43: لقد رأينا بالفعل أن سياق الصفحة يمكن العثور عليه في [this.$nuxt.context
  • السطر 42: نعرض أيضًا خصائص كائن [this.$nuxt

عند تنفيذها بواسطة الخادم، تولد هذه الصفحة السجلات التالية:

[home beforeCreate]
[home server created]
Liste des clés [[home server created], this.$nuxt]
[
  '_uid',
  '_isVue',
  '$options',
  '_renderProxy',
  '_self',
  '$parent',
  '$root',
  '$children',
  '$refs',
  '_watcher',
  '_inactive',
  '_directInactive',
  '_isMounted',
  '_isDestroyed',
  '_isBeingDestroyed',
  '_events',
  '_hasHookEvent',
  '_vnode',
  '_staticTrees',
  '$vnode',
  '$slots',
  '$scopedSlots',
  '_c',
  '$createElement',
  '$attrs',
  '$listeners',
  '_routerRoot',
  '_router',
  '_route',
  '_bv__modal',
  '_bv__toast',
  '_vueMeta',
  'nuxt',
  '_watchers',
  'refreshOnlineStatus',
  'refresh',
  'errorChanged',
  'setLayout',
  'loadLayout',
  '_data',
  'layoutName',
  'layout',
  'isOnline',
  '_computedWatchers',
  'isOffline',
  'error',
  'context'
]

خصائص سياق الخادم في صفحة [index] هي كما يلي:

Liste des clés [[home server created], this.$nuxt.context]
[
  'isStatic',
  'isDev',
  'isHMR',
  'app',
  'payload',
  'error',
  'base',
  'env',
  'req',
  'res',
  'ssrContext',
  'redirect',
  'beforeNuxtRender',
  'route',
  'next',
  '_redirected',
  '_errored',
  'params',
  'query',
  '$axios'
]

هذه هي نفس الخصائص الموجودة في كائن [context] الخاص بالمكوّن الإضافي.

10.5. المكوّن الإضافي الذي يتم تنفيذه من قبل العميل

بمجرد أن يرسل الخادم صفحة [index] إلى متصفح العميل، تتولى البرامج النصية من جانب العميل زمام الأمور. سيتم بعد ذلك تنفيذ المكون الإضافي [main.js]. هذه السجلات هي كما يلي:

[main server], process.server= false process.client= true
[main client], il y a 2 arguments
Liste des clés [[main client], context]
Array(17)0: "isStatic"1: "isDev"2: "isHMR"3: "app"4: "payload"5: "error"6: "base"7: "env"8: "redirect"9: "nuxtState"10: "route"11: "next"12: "_redirected"13: "_errored"14: "params"15: "query"16: "$axios"length: 17__proto__: Array(0)
Liste des clés [[main client], context.app]
Array(14)0: "router"1: "nuxt"2: "head"3: "render"4: "data"5: "beforeCreate"6: "created"7: "mounted"8: "watch"9: "computed"10: "methods"11: "components"12: "context"13: "$axios"length: 14__proto__: Array(0)
Liste des clés [[main client], context.route]
Array(8)0: "name"1: "meta"2: "path"3: "hash"4: "query"5: "params"6: "fullPath"7: "matched"length: 8__proto__: Array(0)
[main client], context.route= ObjectfullPath: "/"hash: ""matched: [{}]meta: [{}]name: "index"params: {}path: "/"query: {}__proto__: Object
Liste des clés [[main client], context.app.router]
Array(10)0: "app"1: "apps"2: "options"3: "beforeHooks"4: "resolveHooks"5: "afterHooks"6: "matcher"7: "fallback"8: "mode"9: "history"length: 10__proto__: Array(0)
Liste des clés [[main client], context.app.router.options.routes]
Array(3)0: "0"1: "1"2: "2"length: 3__proto__: Array(0)
[main client], context.app.router.options.routes= Array(3)0: {path: "/page1", name: "page1", component: ƒ}1: {path: "/page2", name: "page2", component: ƒ}2: {path: "/", name: "index", component: ƒ}length: 3__proto__: Array(0)
inject= function

نجد خصائص مشابهة لتلك الموجودة على جانب الخادم، مع فقدان بعض الخصائص وظهور أخرى. على سبيل المثال، في السطر 4، الخصائص [req, res] —التي كانت طلبات HTTP لمتصفح العميل واستجابة HTTP للخادم— مفقودة.

10.6. صفحة [index] الخاصة بالعميل

تنتج صفحة [index] الخاصة بالعميل السجلات التالية:

1
2
3
4
5
6
7
8
[home beforeCreate]
[home client created]
Liste des clés [[home client created], this.$nuxt]
(51) ["_uid", "_isVue", "$options", "_renderProxy", "_self", "$parent", "$root", "$children", "$refs", "_watcher", "_inactive", "_directInactive", "_isMounted", "_isDestroyed", "_isBeingDestroyed", "_events", "_hasHookEvent", "_vnode", "_staticTrees", "$vnode", "$slots", "$scopedSlots", "_c", "$createElement", "$attrs", "$listeners", "_routerRoot", "_router", "_route", "_bv__modal", "_bv__toast", "_vueMeta", "nuxt", "_watchers", "refreshOnlineStatus", "refresh", "errorChanged", "setLayout", "loadLayout", "_data", "layoutName", "layout", "isOnline", "_computedWatchers", "isOffline", "error", "context", "_name", "setTransitions", "$loading", "$el"]
Liste des clés [[home client created], this.$nuxt.context]
(17) ["isStatic", "isDev", "isHMR", "app", "payload", "error", "base", "env", "redirect", "nuxtState", "route", "next", "_redirected", "_errored", "params", "query", "$axios"]
[home client beforeMount]
[home client mounted]
  • السطر 4: خصائص كائن [this.$nuxt]. إنه كائن غني يحتوي على 51 خاصية؛
  • السطر 6: خصائص كائن [this.$nuxt.context]. هذه هي نفس الخصائص الموجودة في كائن [context] الخاص بمكوّن العميل الإضافي؛