xinpianchang / fe-weekly

weekly for fe-team
10 stars 2 forks source link

Nuxt middleware #102

Open Echo-mz opened 2 years ago

Echo-mz commented 2 years ago

middleware 中间件

其目录结构目录 image image

该 middleware 目录包含您的应用程序中间件。中间件允许您定义可以在呈现页面或一组页面(布局)之前运行的自定义函数。共享中间件应该放在 middleware/ 目录中。文件名将是中间件的名称(middleware/auth.js 将是 auth 中间件)。

export default function (context) {
  // Add the userAgent property to the context
  context.userAgent = process.server
    ? context.req.headers['user-agent']
    : navigator.userAgent
}

在通用模式下,中间件将在服务器端(对 Nuxt 应用程序的第一个请求,例如直接访问应用程序或刷新页面时)和客户端在导航到进一步路由时调用一次。使用ssr: false,在两种情况下都会在客户端调用中间件。

中间件将按以下顺序依次执行:

  1. nuxt.config.js (按文件内的顺序)

  2. 匹配的布局

  3. 匹配的页面

Echo-mz commented 2 years ago

路由器中间件Router Middleware

中间件可以是异步的。为此,请返回 a Promise 或使用 async/await 中间件middleware/stats.js

import http from 'http'

export default function ({ route }) {
  return http.post('http://my-stats-api.com', {
    url: route.fullPath
  })
}

然后在 nuxt.config.js,使用 router.middleware 配置项

export default {
  router: {
    middleware: 'stats'
  }
}

每次路由更改都会调用中间件pages/index.vue /layouts/defalt.vue

export default {
  middleware: ['auth', 'stats']
}
Echo-mz commented 2 years ago

命名中间件Named** middleware

您可以通过在middleware/ 目录中创建一个文件来创建命名中间件 ,文件名将是中间件名称middleware/authenticated.js

export default function ({ store, redirect }) {
  // If the user is not authenticated
  if (!store.state.authenticated) {
    return redirect('/login')
  }
}

使用当前中间件

<template>
  <h1>Secret page</h1>
</template>

<script>
  export default {
    middleware: 'authenticated'
  }
</script>
Echo-mz commented 2 years ago

匿名中间件Anonymous middleware

如果只需要为特定页面使用中间件,则可以直接为其使用函数(或函数数组):

<template>
  <h1>Secret page</h1>
</template>

<script>
  export default {
    middleware({ store, redirect }) {
      // If the user is not authenticated
      if (!store.state.authenticated) {
        return redirect('/login')
      }
    }
  }
</script>
Echo-mz commented 2 years ago

路由更改调用中间件

路由更改时,首先依次调用调用项目中间件,直至完成,接着Vue.use(Router) image

Echo-mz commented 2 years ago

中间件使用和分类

image 中间件功能可以执行以下任务:

  1. 执行任何代码。
  2. 对请求和响应对象进行更改。
  3. 结束请求-响应循环。
  4. 调用堆栈中的下一个中间件

根据中间件的使用场景,大致可以分为以下几类中间件

  1. 应用级别中间件 app.use
  2. 路由级别中间件 router.use
  3. express 内置中间件 express.static,express.json,express.urlencoded
  4. 错误处理中间件 app.use(err,req,res,next)
  5. 第三方中间件 bodyparser,cookieparser
Echo-mz commented 2 years ago

相关文章 服务器端渲染中间件(serverMiddleware) 属性 Nuxt源码 — plugin (middleware) 参数之谜 NuxtJS

Echo-mz commented 2 years ago

middleware Express

dailynodejs commented 2 years ago

1、中间件允许您定义一个自定义函数运行在一个页面或一组页面渲染之前。

dailynodejs commented 2 years ago

在 Nuxt 的项目里面,有一个 middleware 的目录,放置中间件。

核心知识点:

1、它能做什么?

The middleware lets you define custom function to be ran before rendering a page or a group of pages (layouts).

翻译过来就是: 定义一个自定义函数运行在一个页面或者一组页面渲染之前

比如权限判断之类的可以通过中间件来完成。看一个简单的代码片段:

middleware 文件夹里面有一个 admin.js export default ({ store, error, redirect, res, }) => { const { token } = store.state if (!token) { redirect('/login') } }

上面这个代码片段就是从 store 的 state 里面获取 token,没有 token 就重定向到登录。

对比官方给了一个示例(没有箭头函数的简单版本):

export default function (context) { context.userAgent = process.server ? context.req.headers['user-agent'] : navigator.userAgent }

2、函数接受的参数 context 到底包含哪些?

简称上下文,包含的内容太多了,打印的数据太大,比如:

app 最重要的根实例 store error redirect 服务端的 res 和 req 路由里面的 params 和 query 环境配置的 env 当前环境的判断 isClient 改成了 process.client isServer 改成了 process.server isDev

3、配置的地方?

只是在 middleware 里面定义一个函数的 js 文件是不够的,还需要配置

(1)、一般情况下在 nuxt.config.js 里面:

类型是字符串或者数组 router: { middleware: ['user', 'auth'] },

(2)、当然还可以在 .vue 里面配置: middleware: 'auth'

内部深入:

我们看看本地的 .nuxt 文件夹里面有一个 middleware.js const middleware = {} ​ middleware['auth'] = require('../middleware/auth.js') middleware['auth'] = middleware['auth'].default || middleware['auth']

export default middleware

在 server.js 里面如何处理?

1、引入上面的 middleware.js

import middleware from './middleware.js'

2、nuxt.config.js 按顺序配置的其实不只是字符串名字

先拿过来

let midd = ["user","auth"]

然后 map 循环一下,注意下面的 middleware[name] 就和上面呼应了

midd = midd.map((name) => { if (typeof name === 'function') { return name } if (typeof middleware[name] !== 'function') { app.context.error({ statusCode: 500, message: 'Unknown middleware ' + name }) } return middleware[name] })

再处理 layout 和 page 的 .vue 文件里面的 middleware 配置 midd = []

layout 的部分: if (layout.options.middleware) { midd = midd.concat(layout.options.middleware) }

middleware 的部分: Components.forEach((Component) => { if (Component.options.middleware) { midd = midd.concat(Component.options.middleware) } })

有数组了,类似上面的 map 处理:

midd = midd.map((name) => { if (typeof name === 'function') { return name } if (typeof middleware[name] !== 'function') { app.context.error({ statusCode: 500, message: 'Unknown middleware ' + name }) } return middleware[name] })

在 client.js 里面如何处理?

第一步还是引入: import middleware from './middleware.js'

有一个函数 callMiddleware

function callMiddleware (Components, context, layout) { }

里面的代码类似上面,不过不是分开处理,是在一起处理

dailynodejs commented 2 years ago

image

dailynodejs commented 2 years ago

image