Skip to content

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

10.1. Présentation

يهدف المثال [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) {
  // من الذي ينفذ هذا الكود؟
  console.log('[main server], process.server=', process.server, 'process.client=', process.client)
  const who = process.server ? 'server' : 'client'
  const main = '[main ' + who + ']'
  // عدد الحجج
  console.log(main + ', il y a', args.length, 'arguments')

  // الحجة الأولى
  const context = args[0]
  // مفاتيح السياق
  dumpkeys(main + ', context', context)
  // التطبيق
  dumpkeys(main + ', context.app', context.app)
  // المسار
  dumpkeys(main + ', context.route', context.route)
  console.log(main + ', context.route=', context.route)
  // الموجه
  dumpkeys(main + ', context.app.router', context.app.router)
  // 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)

  // الحجة الثانية
  const inject = args[1]
  console.log('inject=', typeof inject)
}

function dumpkeys(message, object) {
  // قائمة مفاتيح [object]
  const ligne = 'Liste des clés [' + message + ']'
  console.log(ligne)
  // قائمة المفاتيح
  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',
   'متطابق'
]

المسار [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] هي التالية:


<!-- الصفحة الرئيسية -->
<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
  },
  data() {
    return {
      who: process.server ? 'server' : 'client'
    }
  },

  // دورة الحياة
  beforeCreate() {
    // العميل والخادم
    console.log('[home beforeCreate]')
  },
  created() {
    // العميل والخادم
    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() {
    // العميل فقط
    console.log('[home ' + this.who + ' beforeMount]')
  },
  mounted() {
    // العميل فقط
    console.log('[home ' + this.who + ' mounted]')
  },
  methods: {
    dumpkeys(message, object) {
      // قائمة مفاتيح [object]
      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] الخاص بالمكوّن الإضافي للعميل؛