Nuxt2 构建 SSR 商城——路由

1,186 阅读4分钟

本篇主要介绍基于 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>

注意事项:

  1. 二级页面需要放在一个新建的文件夹下
  2. 可以定义带参数的动态路由,但文件名必须以 _ 开头,如 _id.vue,id 是动态改变的
  3. <nuxt-link>to 的值可以是写死的,也可以是个对象,可以动态的传递参数,如上例中的第 5 行代码。其中,namevalue 为“目录名-下一级目录名(如果有下一级的话)-文件名”,这里文件名要去掉 "_",params 对象的 key 则是文件名,同样也不要带 "_", value 则为需要传递的参数。
  4. <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。
目录结构如下图:

image.png
在 layouts 目录下的 default.vue 中的 <nuxt /> 所对应的为下图蓝色框区域,在 goods.vue 中的 <nuxt /> 所对应的则为下图红色框区域:

image (1).png
如果我们想让第二级的页面(红色框)占满整个一级展示区域(蓝色框)呢?

  1. 在 goods 目录下新建 index.vue,将 goods.vue 中的内容复制进来
  2. 将 goods.vue 删除
    这样商品详情就会布满整个一级展示区了,如下图:

image (2).png
也就是说,某一目录下的 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>

上述这样的设置会有个问题:/ 指向了首页,而登录页和商品页的路径都有 /,所以当前页面为任何一个页面,首页链接都会是蓝色:

image (3).png

解决:配置扩展路由

在 nuxt.config.js 文件内,找到 router 对象,进行如下配置:

router: { 
  // 扩展路由 
  extendRoutes(routes, resolve) { 
    routes.push({ 
      name: 'index', 
      path: '/index', 
      component: resolve(__dirname, 'pages/index.vue') 
    }) 
  } 
}

其中:

  1. resolve 与 node 里的 path.resolve 中的 resolve 差不多,用于将相对路径转为绝对路径。
  2. __dirname 用于获得当前执行文件(nuxt.config.js)所在目录(项目目录)的完整目录名。
    这样,我们就可以将首页的路径由原来的 / 改成 /index,也就是将链接写成 <nuxt-link active-class="c-blue" to="/index">首页</nuxt-link>

参数校验

可以在 validate 这个生命周期里做路由参数的校验工作,比如针对之前的商品详情页的跳转的路由设定,假定需求是 id2 时不可以跳转到商品详情页,我们可以在 goods 目录下的 _id.vue 页面定义:

export default { 
  validate({ params }) { 
    const { id } = params
    if (id === '1') { 
      return true 
    } else if (id === 2) {
      return fase 
    } 
  } 
}

当点击去往商品 2 的链接时,就会展示一个 nuxt 默认的错误页面。

感谢.gif
点赞.png