本篇主要介绍基于 NuxtJS 构建的 vue 后端渲染(SSR)项目中路由方面的介绍。有不足之处或是任何意见建议,欢迎各位大佬不吝斧正~
约定式路由
nuxt 无需像一般的 vue 项目那样,通过 new Router({})
之类的步骤单独配置路由,而是采用约定式的路由,所有需要用到路由跳转的页面,只需要放在 pages 目录下即可,nuxt 会依据 pages 目录结构自动生成 vue-router 模块的路由配置。在 pages 里的页面都需要定义一个 layout
,来规定该页面如何布局,默认情况下,都是使用 layouts 目录下在构建项目时自动生成的 default.vue 文件,里面有个 <nuxt />
标签,相当于 vue 中的 <router-view />
。
如果有不同的布局,可以在 layouts 目录下新建 vue 文件。比如此次项目中,有个“个人中心”板块,页面的头尾与其它页面不同,我就新建了个 user.vue 文件。下面分别放一下 default.vue 和 user.vue 的 template 部分举个例:
<!-- default.vue -->
<template>
<div>
<div v-if="$nuxt.isOffline">You are offline</div>
<Header />
<nuxt />
<Footer />
</div>
</template>
默认布局是上中下的页面头,页面主体和页面尾 3 部分组成。
P.S. $nuxt.isOffline
是用于做断网检测的。
<!-- user.vue -->
<template>
<div>
<div v-if="$nuxt.isOffline">You are offline</div>
<!-- 顶部导航栏 -->
<Shortcut />
<UserHeader />
<div class="main-content flex-ai_fs m-t_20">
<!-- 侧边栏菜单 -->
<UserNavMenu style="margin-right: 20px" />
<nuxt />
</div>
</div>
</template>
个人中心的页面会多一条很窄的顶部导航栏,然后主体部分是左右结构,左边有个侧边栏菜单,然后右边的 <nuxt />
放写在 pages 目录下的个人中心的页面。
注意:写在 layouts 目录下的布局页面内部的内容是可以分成多个组件的,比如把导航部分单独定义为 Header.vue 组件再引入。
声明式跳转
在 layouts / default.vue 中,可以用 <nuxt-link>
标签声明式跳转页面,相当于 vue 中的 <router-link>
。比如页面头部的 logo,需要点击跳转到首页,只需在 <nuxt-link>
的 to
属性中写上 /index
即可:
<nuxt-link active-class="c-blue" to="/index">
<el-image
style="width: 108px; height: 37px"
src="/imgs/logo.png"
fit="cover"
/>
</nuxt-link>
二级页面
在 pages 目录下新建目录,比如 goods,在 goods 目录下新建 _id.vue, 则在 goods.vue 中,同样可以加上 <nuxt />
作为子页面的展示区,用 <nuxt-link">
进行页面跳转:
<template>
<div>
<h2>商品</h2>
<nuxt-link to="/goods/1?a=1">商品 1</nuxt-link>
<nuxt-link :to="{name: 'goods-id', params: {id: 2}, query: {a: 2}}">商品 2</nuxt-link>
<nuxt />
</div>
</template>
注意事项:
- 二级页面需要放在一个新建的文件夹下
- 可以定义带参数的动态路由,但文件名必须以 _ 开头,如 _id.vue,id 是动态改变的
<nuxt-link>
中to
的值可以是写死的,也可以是个对象,可以动态的传递参数,如上例中的第 5 行代码。其中,name
的value
为“目录名-下一级目录名(如果有下一级的话)-文件名”,这里文件名要去掉 "_",params
对象的 key 则是文件名,同样也不要带 "_", value 则为需要传递的参数。<nuxt-link to="/goods/1?a=1">
中的参数id
的值1
是字符串,而<nuxt-link :to="{name: 'goods-id', params: {id: 2}, query: {a: 2}}">
中的id
的值2
是数字。
展示区层级
为了说明这个问题,我们简单的先创建了 2 级页面:第一级是 index.vue、goods.vue 和 login.vue,它们都是在 pages 目录下的第一级文件;第二级是 goods 目录下的 _id.vue。
目录结构如下图:
在 layouts 目录下的 default.vue 中的 <nuxt />
所对应的为下图蓝色框区域,在 goods.vue 中的 <nuxt />
所对应的则为下图红色框区域:
如果我们想让第二级的页面(红色框)占满整个一级展示区域(蓝色框)呢?
- 在 goods 目录下新建 index.vue,将 goods.vue 中的内容复制进来
- 将 goods.vue 删除
这样商品详情就会布满整个一级展示区了,如下图:
也就是说,某一目录下的 index.vue 内的 <nuxt />
展示区的展示区域同上一级的展示区相同。
扩展路由
除了约定式路由,我们也可以像一般 vue 项目那样自己配置路由。
需求
需要将当前页面的链接文字改为蓝色:我们可以添加 active-class
来设置链接激活时使用的 CSS 类名。
<nuxt-link active-class="c-blue" to="/">首页</nuxt-link>
<nuxt-link active-class="c-blue" to="/login">登录</nuxt-link>
<nuxt-link active-class="c-blue" to="/goods">商品</nuxt-link>
上述这样的设置会有个问题:/
指向了首页,而登录页和商品页的路径都有 /
,所以当前页面为任何一个页面,首页链接都会是蓝色:
解决:配置扩展路由
在 nuxt.config.js 文件内,找到 router
对象,进行如下配置:
router: {
// 扩展路由
extendRoutes(routes, resolve) {
routes.push({
name: 'index',
path: '/index',
component: resolve(__dirname, 'pages/index.vue')
})
}
}
其中:
resolve
与 node 里的path.resolve
中的resolve
差不多,用于将相对路径转为绝对路径。- __dirname 用于获得当前执行文件(nuxt.config.js)所在目录(项目目录)的完整目录名。
这样,我们就可以将首页的路径由原来的/
改成/index
,也就是将链接写成<nuxt-link active-class="c-blue" to="/index">首页</nuxt-link>
参数校验
可以在 validate
这个生命周期里做路由参数的校验工作,比如针对之前的商品详情页的跳转的路由设定,假定需求是 id
为 2
时不可以跳转到商品详情页,我们可以在 goods 目录下的 _id.vue 页面定义:
export default {
validate({ params }) {
const { id } = params
if (id === '1') {
return true
} else if (id === 2) {
return fase
}
}
}
当点击去往商品 2 的链接时,就会展示一个 nuxt 默认的错误页面。