Skip to content

11. Beispiel [nuxt-08]: Routing-Middleware

In diesem Beispiel stellen wir das Konzept der Routing-Middleware vor, also Skripte, die bei jeder Änderung einer Route ausgeführt werden.

Beispiel [nuxt-08] wird zunächst durch Klonen des Projekts [nuxt-01] erstellt:

Image

Routing-Middleware muss in einem Ordner namens [middleware] [2] abgelegt werden. Es kann ein zweistufiges Routing geben:

  • Routing, das auf jede Navigation angewendet wird. Dies wird dann in der Datei [nuxt.config.js] deklariert;
  • Routing, das auf eine bestimmte Seite angewendet wird, wenn diese Seite das Routing-Ziel ist. Dieses Routing wird dann auf dieser Zielseite deklariert;

11.1. Allgemeines Routing

Die Datei [middleware/routing.js] übernimmt das allgemeine Routing. Sie wird in der Datei [nuxt.config.js] wie folgt deklariert:


  router: {
    base: '/nuxt-08/',
    middleware: ['routing']
},

Allgemeine Routing-Middleware ist eine Eigenschaft des Routers (Zeile 1). Es kann mehrere Routing-Middleware-Komponenten geben. Deshalb ist der Wert der Eigenschaft [middleware] in Zeile 3 ein Array. Beachten Sie, dass wir keinen Pfad zur Angabe der Middleware verwenden. Sie wird automatisch im Ordner [middleware] des Projekts gesucht;

Die [routing]-Middleware protokolliert hier nur:


/* eslint-disable no-undef */
/* eslint-disable no-console */
export default function(...args) {
  // who executes this code?
  console.log('[routing], process.server=', process.server, 'process.client=', process.client)
  const who = process.server ? 'server' : 'client'
  const routing = '[routing ' + who + ']'
  // number of arguments
  console.log(routing + ', il y a', args.length, 'argument(s)')
 
  // 1st argument
  const context = args[0]
  // key context
  dumpkeys(routing + ', context', context)
  // the application
  dumpkeys(routing + ', context.app', context.app)
  // the road
  dumpkeys(routing + ', context.route', context.route)
  console.log(routing + ', context.route=', context.route)
  // the router
  dumpkeys(routing + ', context.app.router', context.app.router)
  // on router.options.routes
  dumpkeys(routing + ', context.app.router.options.routes', context.app.router.options.routes)
  console.log(routing + ', context.app.router.options.routes=', context.app.router.options.routes)
}
 
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))
  }
}
  • Zeile 3: Wir werden sehen, dass die Middleware ein Argument erhält: den Kontext des Ausführenden (Server oder Client);
  • Zeilen 4–25: Wir zeigen die Eigenschaften verschiedener Objekte an, um festzustellen, was verwendbar ist. Wir werden feststellen, dass der Middleware-Kontext fast identisch mit dem Plugin-Kontext ist;

11.2. Weiterleitung zu einer bestimmten Seite

Wir möchten steuern, wie Benutzer auf die [index]-Seite gelangen. Dazu müssen wir dieser [index]-Seite die Eigenschaft [middleware] hinzufügen:


<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() {
    // client and server
    console.log('[home beforeCreate]')
  },
  created() {
    // client and server
    console.log('[home created]')
  },
  beforeMount() {
    // customer only
    console.log('[home beforeMount]')
  },
  mounted() {
    // customer only
    console.log('[home mounted]')
  },
  // routing
  middleware: ['index-routing']
}
</script>
  • Zeile 34: Die Eigenschaft [middleware] listet die Skripte auf, die ausgeführt werden sollen, wenn die nächste angezeigte Seite die [index]-Seite ist. Auch hier wird im [middleware]-Ordner des Projekts nach diesen Skripten gesucht;

Die [index-routing]-Middleware sieht wie folgt aus:


/* eslint-disable no-undef */
/* eslint-disable no-console */
export default function(...args) {
  // who executes this code?
  console.log('[index-routing], process.server=', process.server, 'process.client=', process.client)
  const who = process.server ? 'server' : 'client'
  const indexRouting = '[index-routing ' + who + ']'
  // number of arguments
  console.log(indexRouting + ', il y a', args.length, 'argument(s)')
 
  // 1st argument
  const context = args[0]
  // key context
  dumpkeys(indexRouting + ', context', context)
  // the application
  dumpkeys(indexRouting + ', context.app', context.app)
  // the road
  dumpkeys(indexRouting + ', context.route', context.route)
  console.log(indexRouting + ', context.route=', context.route)
  // the router
  dumpkeys(indexRouting + ', context.app.router', context.app.router)
  // on router.options.routes
  dumpkeys(indexRouting + ', context.app.router.options.routes', context.app.router.options.routes)
  console.log(indexRouting + ', context.app.router.options.routes=', context.app.router.options.routes)
  // where do we come from?
  if (context.from) {
    console.log('from=', context.from)
  }
}
 
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))
  }
}

Der Code für [index-routing] ist identisch mit dem von [routing] und liefert die gleichen Ergebnisse. Uns interessiert, wann diese beiden Middlewares ausgeführt werden.

11.3. Ausführen des Projekts

Wir führen das Projekt aus. Die Protokolle sehen wie folgt aus:

Das Skript [routing] wird vom Server zuerst ausgeführt:

[routing], process.server= true process.client= false
[routing server], il y a 1 argument(s)
Liste des clés [[routing server], context]
[ 'isStatic',
  'isDev',
  'isHMR',
  'app',
  'payload',
  'error',
  'base',
  'env',
  'req',
  'res',
  'ssrContext',
  'redirect',
  'beforeNuxtRender',
  'route',
  'next',
  '_redirected',
  '_errored',
  'params',
  'query',
  '$axios' ]
Liste des clés [[routing server], context.app]
[ 'router',
  'nuxt',
  'head',
  'render',
  'data',
  'beforeCreate',
  'created',
  'mounted',
  'watch',
  'computed',
  'methods',
  'components',
  'context',
  '$axios' ]
Liste des clés [[routing server], context.route]
[ 'name',
  'meta',
  'path',
  'hash',
  'query',
  'params',
  'fullPath',
  'matched' ]
[routing 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: {} } ] }
Liste des clés [[routing server], context.app.router]
[ 'app',
  'apps',
  'options',
  'beforeHooks',
  'resolveHooks',
  'afterHooks',
  'matcher',
  'fallback',
  'mode',
  'history' ]
Liste des clés [[routing server], context.app.router.options.routes]
[ '0', '1', '2' ]
[routing server], context.app.router.options.routes= [ { path: '/page1',
    component: [Function: _61cefe10],
    name: 'page1' },
  { path: '/page2',
    component: [Function: _61dd1591],
    name: 'page2' },
  { path: '/', component: [Function: _00d5e140], name: 'index' } ]

Dies ist das gleiche Ergebnis, das wir mit den Plugins erhalten haben.

  • Zeile 15: Die Eigenschaft [redirect] wird häufig in Middleware verwendet; sie ermöglicht es Ihnen, das Ziel des aktuellen Routings zu ändern;

Da es sich bei der anzuzeigenden Seite um die [index]-Seite handelt, führt der Server das Skript [index-routing] aus und zeigt die folgenden Protokolle an:

[index-routing], process.server= true process.client= false
[index-routing server], il y a 1 argument(s)
Liste des clés [[index-routing server], context]
[ 'isStatic',
  'isDev',
  'isHMR',
  'app',
  'payload',
  'error',
  'base',
  'env',
  'req',
  'res',
  'ssrContext',
  'redirect',
  'beforeNuxtRender',
  'route',
  'next',
  '_redirected',
  '_errored',
  'params',
  'query',
  '$axios' ]
Liste des clés [[index-routing server], context.app]
[ 'router',
  'nuxt',
  'head',
  'render',
  'data',
  'beforeCreate',
  'created',
  'mounted',
  'watch',
  'computed',
  'methods',
  'components',
  'context',
  '$axios' ]
Liste des clés [[index-routing server], context.route]
[ 'name',
  'meta',
  'path',
  'hash',
  'query',
  'params',
  'fullPath',
  'matched' ]
[index-routing 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: {} } ] }
Liste des clés [[index-routing server], context.app.router]
[ 'app',
  'apps',
  'options',
  'beforeHooks',
  'resolveHooks',
  'afterHooks',
  'matcher',
  'fallback',
  'mode',
  'history' ]
Liste des clés [[index-routing server], context.app.router.options.routes]
[ '0', '1', '2' ]
[index-routing server], context.app.router.options.routes= [ { path: '/page1',
    component: [Function: _61cefe10],
    name: 'page1' },
  { path: '/page2',
    component: [Function: _61dd1591],
    name: 'page2' },
  { path: '/', component: [Function: _00d5e140], name: 'index' } ]

Die mit dem Skript [index-routing] erzielten Ergebnisse ähneln denen, die mit dem Skript [routing] erzielt wurden.

Sobald die [index]-Seite vom Browser des Clients empfangen wurde, übernehmen die Client-Skripte. Die Protokolle sehen dann wie folgt aus:

1
2
3
4
[home beforeCreate]
[home created]
[home beforeMount]
[home mounted]

Wir sehen also, dass der Client beim Start der Anwendung keine Middleware ausführt. Das bedeutet, dass dies jedes Mal geschieht, wenn der Benutzer eine Anfrage an den Server sendet. Middleware wird vom Client nur ausgeführt, wenn innerhalb des Clients navigiert wird. Navigieren wir beispielsweise über den Link [Seite 1] zur Seite [Seite 1] (wir befinden uns derzeit auf der Seite [Index]). Die Protokolle sehen dann wie folgt aus:

[routing], process.server= false process.client= true
[routing client], il y a 1 argument(s)
Liste des clés [[routing client], context]
(18) ["isStatic", "isDev", "isHMR", "app", "payload", "error", "base", "env", "redirect", "nuxtState", "route", "next", "_redirected", "_errored", "params", "query", "$axios", "from"]
Liste des clés [[routing client], context.app]
(14) ["router", "nuxt", "head", "render", "data", "beforeCreate", "created", "mounted", "watch", "computed", "methods", "components", "context", "$axios"]
Liste des clés [[routing client], context.route]
(8) ["name", "meta", "path", "hash", "query", "params", "fullPath", "matched"]
[routing client], context.route= {name: "page1", meta: Array(1), path: "/page1", hash: "", query: {}, }
Liste des clés [[routing client], context.app.router]
(10) ["app", "apps", "options", "beforeHooks", "resolveHooks", "afterHooks", "matcher", "fallback", "mode", "history"]
Liste des clés [[routing client], context.app.router.options.routes]
(3) ["0", "1", "2"]
[routing client], context.app.router.options.routes= (3) [{}, {}, {}]0: {path: "/page1", name: "page1", component: ƒ}1: {path: "/page2", name: "page2", component: ƒ}2: {path: "/", name: "index", component: ƒ}length: 3__proto__: Array(0)
[page1 beforeCreate]
[page1 created]
[page1 beforeMount]
[page1 mounted]
  • Zeile 2: Die [routing]-Middleware wird vom Client ausgeführt;
  • Zeile 4: Beachten Sie die Eigenschaft [from]: Dies ist die Route, von der wir gekommen sind;
  • Zeile 9: [context.route] ist die Route, zu der wir gehen;
  • Zeilen 15–18: Anzeige der Seite [page1];

Kehren wir nun über den Link [Home] zur Seite [index] zurück. Die Protokolle sehen dann wie folgt aus:

[routing], process.server= false process.client= true
[routing client], il y a 1 argument(s)
Liste des clés [[routing client], context]
(18) ["isStatic", "isDev", "isHMR", "app", "payload", "error", "base", "env", "redirect", "nuxtState", "route", "next", "_redirected", "_errored", "params", "query", "$axios", "from"]
Liste des clés [[routing client], context.app]
(14) ["router", "nuxt", "head", "render", "data", "beforeCreate", "created", "mounted", "watch", "computed", "methods", "components", "context", "$axios"]
Liste des clés [[routing client], context.route]
(8) ["name", "meta", "path", "hash", "query", "params", "fullPath", "matched"]
[routing client], context.route= {name: "index", meta: Array(1), path: "/", hash: "", query: {}, }
Liste des clés [[routing client], context.app.router]
(10) ["app", "apps", "options", "beforeHooks", "resolveHooks", "afterHooks", "matcher", "fallback", "mode", "history"]
Liste des clés [[routing client], context.app.router.options.routes]
(3) ["0", "1", "2"]
[routing client], context.app.router.options.routes= (3) [{}, {}, {}]0: {path: "/page1", name: "page1", component: ƒ}1: {path: "/page2", name: "page2", component: ƒ}2: {path: "/", name: "index", component: ƒ}length: 3__proto__: Array(0)
[index-routing], process.server= false process.client= true
[index-routing client], il y a 1 argument(s)
Liste des clés [[index-routing client], context]
(18) ["isStatic", "isDev", "isHMR", "app", "payload", "error", "base", "env", "redirect", "nuxtState", "route", "next", "_redirected", "_errored", "params", "query", "$axios", "from"]
Liste des clés [[index-routing client], context.app]
(14) ["router", "nuxt", "head", "render", "data", "beforeCreate", "created", "mounted", "watch", "computed", "methods", "components", "context", "$axios"]
Liste des clés [[index-routing client], context.route]
(8) ["name", "meta", "path", "hash", "query", "params", "fullPath", "matched"]
[index-routing client], context.route= {name: "index", meta: Array(1), path: "/", hash: "", query: {}, }
Liste des clés [[index-routing client], context.app.router]
(10) ["app", "apps", "options", "beforeHooks", "resolveHooks", "afterHooks", "matcher", "fallback", "mode", "history"]
Liste des clés [[index-routing client], context.app.router.options.routes]
(3) ["0", "1", "2"]
[index-routing client], context.app.router.options.routes= (3) [{}, {}, {}]0: {path: "/page1", name: "page1", component: ƒ}1: {path: "/page2", name: "page2", component: ƒ}2: {path: "/", name: "index", component: ƒ}length: 3__proto__: Array(0)
from= {name: "page1", meta: Array(1), path: "/page1", hash: "", query: {}, }
[home beforeCreate]
[home created]
[home beforeMount]
[home mounted]
  • Zeilen 1–15: Der Client führt die [routing]-Middleware aus. Das ist normal. Sie wird jedes Mal ausgeführt, wenn sich die Route ändert;
  • Zeilen 16–29: Der Client führt die [index-routing]-Middleware aus, weil:
    • [index] das Ziel der aktuellen Route ist (siehe Zeile 23);
    • die [index]-Seite eine Middleware namens [index-routing] definiert hat;

Wir sehen also, dass die allgemeine Routing-Middleware vom Client vor der an die Seiten angehängten Middleware ausgeführt wird.