二、将Vue项目改造成Nuxt项目-关于页面路由

路由

nuxt的路由没有router文件,nuxt的路由就是page文件夹下的文件目录

以下目录结构

1
2
3
4
5
6
7
pages/
--| _slug/
-----| comments.vue
-----| index.vue
--| users/
-----| _id.vue
--| index.vue

Nuxt.js 生成对应的路由配置表为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
router: {
routes: [
{
name: 'index',
path: '/',
component: 'pages/index.vue'
},
{
name: 'users-id',
path: '/users/:id?',
component: 'pages/users/_id.vue'
},
{
name: 'slug',
path: '/:slug',
component: 'pages/_slug/index.vue'
},
{
name: 'slug-comments',
path: '/:slug/comments',
component: 'pages/_slug/comments.vue'
}
]
}

看到上面的_slug_id了吗,这是nuxt的动态路由,其中_slug是目录,_id是文件,动态目录下的index.vue是默认跳转的路由,这代表:

  1. http://localhost:3000/ahttp://localhost:3000/b 打开的文件是 pages/_slug/index.vue
  2. http://localhost:3000/a/commentshttp://localhost:3000/b/comments 打开的文件是 pages/_slug/comments.vue
  3. http://localhost:3000/users/123http://localhost:3000/users/abc 打开的文件是 pages/users/_id.vue

动态嵌套路由

nuxt也可以在在动态路由下配置动态子路由。

假设文件结构如下:

1
2
3
4
5
6
7
8
9
pages/
--| _category/
-----| _subCategory/
--------| _id.vue
--------| index.vue
-----| _subCategory.vue
-----| index.vue
--| _category.vue
--| index.vue

Nuxt.js 自动生成的路由配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
router: {
routes: [
{
path: '/',
component: 'pages/index.vue',
name: 'index'
},
{
path: '/:category',
component: 'pages/_category.vue',
children: [
{
path: '',
component: 'pages/_category/index.vue',
name: 'category'
},
{
path: ':subCategory',
component: 'pages/_category/_subCategory.vue',
children: [
{
path: '',
component: 'pages/_category/_subCategory/index.vue',
name: 'category-subCategory'
},
{
path: ':id',
component: 'pages/_category/_subCategory/_id.vue',
name: 'category-subCategory-id'
}
]
}
]
}
]
}

这里注意:_category.vue_category/同级

路由参数校验

在动态路由中可以设置参数校验,例如文章详情页的路由是http://localhost:3000/article/123456123456是文章id,文章id永远都是数字,不可能是汉字,所以可以在pages/article/_id.vue页面校验一下参数:

1
2
3
4
5
6
export default {
validate ({ params }) {
// 必须是number类型
return /^\d+$/.test(params.id)
}
}

如果校验方法返回的值不为 true或Promise中resolve 解析为false或抛出Error , Nuxt.js 将自动加载显示 404 错误页面或 500 错误页面。

新建error.vue页面在layouts文件夹中,在error.vue页面中可以捕获到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<div>
<not-found v-if="error.statusCode==404"></not-found>
<error-page v-else></error-page>
</div>
</template>
<script>
import notFound from '~/components/404.vue'
import errorPage from '~/components/500.vue'
export default {
props: ['error'],
components: { notFound, errorPage }
}
</script>

路由中间件

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

它可以做到在打开页面或者切换路由之前,加一些判断,例如重定向之类的操作。
中间件放在middleware文件夹中,文件名就是中间件的名字(middleware/auth.js将成为 auth 中间件)
中间件的配置方式:

1
2
3
4
5
6
// nuxt.config.js
module.exports = {
router: {
middleware: 'stats'
}
}

可以再中间件中加重定向:

1
2
3
4
5
6
7
export default function ({ isHMR, redirect }) {
if (isHMR) return

if (route.fullPath == '/') {
return redirect('/all')
}
}

还可以加一些其他操作,例如将userAgent赋值给context:

1
2
3
4
5
6
7
8
export default function ({ isHMR, app, req, store, route, params, error, redirect }) {
if (isHMR) return
context.userAgent = process.server ? context.req.headers['user-agent'] : navigator.userAgent

if (route.fullPath == '/') {
return redirect('/all')
}
}

这样的话,在红框,黄框周期内就可以愉快的使用userAgent了:

1
2
3
4
5
6
7
validate (context) {
console.log(1, context.userAgent)
return true
},
asyncData (context) {
console.log(2, context.userAgent)
}

img