约定式路由

约定式路由是nuxt已经约定好的路由定义方式。

nuxt的普通路由

nuxt的路由无需单独配置,他会自动读取pages下的文件名作为路由地址,访问对应的路由地址就会显示对应的页面。
在nuxt中<nuxt>标签相当于<router-view><nuxt-link>相当于<router-link>

Nuxt 路由的原理是基于 vue-router,并根据文件名从 pages/ 目录中创建的每个组件生成路由。

一级路由

layout/default.vue是页面默认显示的内容
layout/default.vue

<template>
  <div>
    <!-- 跳转区 nuxt-link -->
    <nuxt-link to="/">首页</nuxt-link>
    <nuxt-link to="/goods">商品</nuxt-link>
    <nuxt-link to="/user">用户</nuxt-link>
    <nuxt-link to="/login">登录</nuxt-link>
    <nuxt-link to="/reg">注册</nuxt-link>

    <!-- 展示区,相当于routerview -->
    <nuxt />
  </div>
</template>
<script>

export default {
  // layout层级中间件
  // 1. 引用外部中间件
  middleware: 'auth',
  // 2. 使用内部中间件
  middleware() {
    console.log('layout middleware')
  }
}
</script>

pages目录:
在这里插入图片描述
goods.vue

<template>
    <div class="goods">
        <h1>商品</h1>
    </div>
</template>

页面:
在这里插入图片描述

二级路由

在这里插入图片描述
pages/test/secondRouter.vue

<template>
    <div class="goods">
        <h1>第二级路由</h1>
    </div>
</template>

在这里插入图片描述

动态路由

如果是动态路由,路由页面的名称是以下划线_开头的。
动态路由中参数存储在this.$route.params中,可以通过该变量获取参数。
pages/goods.vue

<template>
    <div class="goods">
        <h1>商品</h1>
        <nuxt-link to="/goods/1">商品01</nuxt-link>
        <nuxt-link to="/goods/2">商品02</nuxt-link>
        <!-- 展示区 -->
        <nuxt/>
    </div>
</template>

动态路由页面:pages/goods/_id.vue
在这里插入图片描述

<template>
    <div>
        <h2>商品{{ goodsId }}的详情页</h2>
    </div>
</template>
<script>
export default {
    data() {
        return {
            goodsId: this.$route.params.id
        }
    }
}
</script>

在这里插入图片描述
在这里插入图片描述

路由参数

路由后面可以携带?a=1&b=2代表路由的参数,路由参数存储在this.$route.query中。
eg:
pages/goods.vue

<template>
    <div class="goods">
        <h1>商品</h1>
        <nuxt-link to="/goods/1?a=1&b=11">商品01</nuxt-link>
        <nuxt-link to="/goods/2">商品02</nuxt-link>
        <!-- goods商品详情的展示区 -->
        <nuxt/>
    </div>
</template>

路由参数:pages/goods/_id.vue

<template>
    <div>
        <h2>商品{{ goodsId }}的详情页</h2>
        <h3>携带参数: a:{{ a }},b:{{ b }}</h3>
    </div>
</template>
<script>
export default {
    data() {
        return {
            goodsId: this.$route.params.id,
            a: this.$route.query.a,
            b: this.$route.query.b,
        }
    }
}
</script>


在这里插入图片描述
在这里插入图片描述

路由的对象写法

之前的路由都是用字符串的写法,也可以用对象方法写:

  • name:路由地址,动态路由使用-连接,从pages的下一级开始写
  • params:{id:1}:动态路由参数,变量名和动态路由页面的名一样
  • query:{变量:变量值} 路由参数
    eg:
    上面的
<nuxt-link to="/goods/1?a=1&b=11">商品01</nuxt-link>

可以写成

<nuxt-link :to="{name:'goods-id', params:{id:1}, query:{a:1,b:11}}">商品01</nuxt-link>

name:‘目录名-其他目录-文件名(如果是动态路径名不带_)’,从pages目录的下一级开始一直到目标页面为止。
params:动态路径名的参数(params参数)。
query:携带的query参数。

嵌套路由

三级嵌套路由——第二级静态第三级动态

上述案例中goods下面的商品页面(_id)是二级路由,二级路由还可以嵌套下一级路由,就是在goods文件夹下继续嵌套:
在这里插入图片描述
pages/goods/comment.vue

<template>
    <div>
        <h4>评论</h4>
        <nuxt-link :to="{ name: 'goods-comment-uid', params: { uid: 1 }}">评论1</nuxt-link>
        <nuxt-link to="/goods/comment/2">评论2</nuxt-link>
        <!-- 评论展示区 -->
        <nuxt/>

    </div>
</template>
<script>
export default {
    data() {
    }
}
</script>

pages/goods/comment/_uid.vue

<template>
  <div>
    <p>评论{{ commentId }}的详情页</p>
  </div>
</template>
<script>
  export default {
    data() {
      console.log(" this.$route", this.$route);
        return {
            commentId: this.$route.params.uid,
        }
    },
  };
</script>

实现效果:
在这里插入图片描述

三级嵌套路由——第二级、三级动态

动态路由下面当然可以继续嵌套动态路由。
如:商品下面继续嵌套款式信息
在这里插入图片描述
pages/goods/_id.vue

<template>
    <div>
        <h2>商品{{ goodsId }}的详情页</h2>
        <h3>携带参数: a:{{ a }},b:{{ b }}</h3>
        <h4>款式</h4>
        <nuxt-link :to="`/goods/${goodsId}/1`">款式1</nuxt-link>
        <nuxt-link :to="`/goods/${goodsId}/2`">款式2</nuxt-link>
        <nuxt/>
    </div>
</template>
<script>
export default {
    data() {
        return {
            goodsId: this.$route.params.id,
            a: this.$route.query.a,
            b: this.$route.query.b,
        }
    }
}
</script>

pages/goods/_id/_sid.vue

<template>
    <div>
        <p>商品{{`商品${goodsId}的款式${styleId}的详情页`}}的详情页</p>
    </div>
</template>
<script>
export default {
    data() {
        return {
            styleId: this.$route.params.sid,
            goodsId: this.$route.params.id,
        }
    },
};
</script>

效果:
在这里插入图片描述

三级嵌套路由——第二级动态第三级静态

动态路由的下一级当然也可以是动态的
在这里插入图片描述
pages/goods/_id.vue

<template>
    <div>
        <h2>商品{{ goodsId }}的详情页</h2>
        <h3>携带参数: a:{{ a }},b:{{ b }}</h3>
        <!-- <h4>款式</h4>
        <nuxt-link :to="`/goods/${goodsId}/1`">款式1</nuxt-link>
        <nuxt-link :to="`/goods/${goodsId}/2`">款式2</nuxt-link>
        <nuxt/> -->
        <h4>生产商</h4>
        <nuxt-link :to="`/goods/${goodsId}/producer`">生产商是:</nuxt-link>
        <nuxt/>
    </div>
</template>
<script>
export default {
    data() {
        return {
            goodsId: this.$route.params.id,
            a: this.$route.query.a,
            b: this.$route.query.b,
        }
    }
}
</script>

pages/goods/_id/producer.vue

<template>
    <div>
        <p>商品{{goodsId}}的生产商是:{{ goodsId==='1'?'百度':'google' }}</p>
    </div>
</template>
<script>
export default {
    data() {
        return {
            goodsId: this.$route.params.id,
        }
    },
};
</script>

实现效果:
在这里插入图片描述

展示区

<nuxt/>标签所占用的位置就是展示区的位置。
上述案例各级展示区的区域如图所示:
在这里插入图片描述

二级展示区的内容放到一级展示区进行展示

商品的详情页可以放在商品的页面进行展示,只需要将page/goods.vue删除添加到page/goods/index.vue
在这里插入图片描述
效果:
商品页:
在这里插入图片描述
详情页:
在这里插入图片描述
我们可以发现,商品的详情页虽然是二级路由,由于我们修改写法,它现在展示的区域是一级路由的区域。

默认展示页

在nuxt框架中路由默认展示的页面就是对应文件夹中的index文件,上述的例子访问/goods路由就会默认展示goods文件夹中的index.vue文件。如果没有index.vue文件就会默认显示第一个其余的文件内容。

**案例:**评论页面会将评论的详情页面也默认展示,效果如下:
在这里插入图片描述
这是因为comment文件夹中有且仅有一个文件_uid.vue,所以访问评论的时候就会默认展示该页面。
在这里插入图片描述
我们可以在comment下添加一个index.vue文件,里面不编写任何内容,访问评论的时候就没有详情页了:
在这里插入图片描述
效果:
在这里插入图片描述

展示区展示总结

展示区层级控制:
PATHFILE
/index.vue
/goodsgoods/index.vue 或 goods.vue
/goods/123goods/_id.vue
/goods/commentgoods/commoent.vue 或 goods/commoent/index.vue
nuxt路由的两种展示方式
  • 常规的展示方式
    常规的展示方式是访问 pages/一级路由名/ 二级路由名/ .../ n级路由名展示的是 pages/一级路由名/ 二级路由名/ .../ n级路由名.vue

以一级路由下的二级路由为例:
pages/goods/comment.vue表示展示的是商品目录下的评论页面
此时,项目的目录结构是

#  展示goods页面的主体内容
/pages/goods.vue 

#  展示goods下的评论内容
/pages/goods/comment.vue 

展示效果是;
在这里插入图片描述

  • index的展示方式
    index的展示方式是访问 pages/一级路由名/ 二级路由名/ .../ n级路由名展示的是 pages/一级路由名/ 二级路由名/ .../ n级路由名/index.vue

以一级路由下的二级路由为例:
pages/goods/comment.vue表示展示的是商品目录下的评论页面
此时,项目的目录结构是

#  展示goods页面的主体内容
/pages/goods/index.vue 

#  展示goods下的评论内容
/pages/goods/comment.vue 

展示效果是;
在这里插入图片描述

路由的导航栏展示

路由一般会对应导航栏,上述例子中的导航栏是以nuxt-link的格式进行展示的,我们可以将导航栏的展示作为一个组件提取出来。我们可以将提取出来的组件放在layout文件夹下,layout文件夹下的组件文件默认导出来。
原layout/defaut.vue文件:

<template>
  <div>
    <!-- 跳转区 nuxt-link -->
    <AppHeader></AppHeader>
    <!-- 展示区,相当于routerview -->
    <nuxt />
  </div>
</template>
<script>

import AppHeader from './app-header.vue'
export default {
  // // layout层级中间件
  // // 1. 引用外部中间件
  // middleware: 'auth',
  // // 2. 使用内部中间件
  // middleware() {
  //   console.log('layout middleware')
  // }
  components:{ AppHeader }
}
</script>

修改后的文件:
layout/default.vue

<template>
  <div>
    <!-- 跳转区 nuxt-link -->
    <AppHeader></AppHeader>
    <!-- 展示区,相当于routerview -->
    <nuxt />
  </div>
</template>
<script>

import AppHeader from './app-header.vue'
export default {
  // // layout层级中间件
  // // 1. 引用外部中间件
  // middleware: 'auth',
  // // 2. 使用内部中间件
  // middleware() {
  //   console.log('layout middleware')
  // }
  components:{ AppHeader }
}
</script>

layout/app-header.vue

<template>
    <nav>
        <!-- <nuxt-link to="/index" active-class="app_header--active">首页</nuxt-link> -->
        <nuxt-link to="/"  exact-active-class="app_header--active">首页</nuxt-link>
        <nuxt-link to="/goods" active-class="app_header--active">商品</nuxt-link>
        <nuxt-link to="/user" active-class="app_header--active">用户</nuxt-link>
        <nuxt-link to="/login" active-class="app_header--active">登录</nuxt-link>
        <nuxt-link to="/reg" active-class="app_header--active">注册</nuxt-link>
    </nav>
</template>
<style scoped>
.app_header--active{
    background: black;
    color: white;
}
</style>

效果:
在这里插入图片描述

扩展式路由

上面的都是约定式路由,即路由不需要我们手动配置,页面的路径地址即路由地址。在nuxt中当然也可以手动配置路由,我们需要在nuxt.config.js进行路由配置。
eg:
app-header.vue

<template>
    <nav>
        <!-- <nuxt-link to="/index"  active-class="app_header--active">首页</nuxt-link> -->
        <nuxt-link to="/goods" active-class="app_header--active">商品</nuxt-link>
        <nuxt-link to="/user" active-class="app_header--active">用户</nuxt-link>
        <nuxt-link to="/login" active-class="app_header--active">登录</nuxt-link>
        <nuxt-link to="/reg" active-class="app_header--active">注册</nuxt-link>
    </nav>
</template>
<style scoped>
.app_header--active{
    background: black;
    color: white;
} 
</style>

app-header.vue中没有配置index路径的访问组件,在nuxt.config.js中设置如下路由:



export default {
  // 服务端渲染模式,同构
  mode: 'universal',
  /*
  ** 页面Head
  */
  head: {
   ...
  },
  /**
   * 路由配置
   */
  router: {
    middleware: 'auth',
    /**
     * nuxt每次启动都会执行extendRoutes函数
     * @param {*routes} routes 所有路由信息
     * @param {*resolve} resolve 磁盘上的所有函数
     */
    extendRoutes(routes, resolve) {
      console.log('route', routes);
      // 扩展路由
      // 添加路由
      routes.push({
        name: 'home',//路由别名
        path: '/index',//路由路径
        component: resolve(__dirname, 'pages/index.vue')//显示组件
      })   
    }
  },  
}

访问/index就会显示pages/index.vue的内容:
在这里插入图片描述

路由的参数校验

路由参数的校验放在每个组件中,通过validate函数进行参数的校验。
第一个参数是params参数,第二个参数是query参数。

validate({ params, query }) {
        console.log("params====", params, query); 
    },

eg:限制商品详情页的参数是number类型
pages/goods/_id.vue

<template>
    <div style="background:rgb(255, 255, 152)">
        <h2>商品{{ goodsId }}的详情页</h2>
        <h3>携带参数: a:{{ a }},b:{{ b }}</h3>
        <!-- <h4>款式</h4>
        <nuxt-link :to="`/goods/${goodsId}/1`">款式1</nuxt-link>
        <nuxt-link :to="`/goods/${goodsId}/2`">款式2</nuxt-link>
        <nuxt/> -->
        <h4>生产商</h4>
        <nuxt-link :to="`/goods/${goodsId}/producer`">生产商是:</nuxt-link>
        <nuxt/>
    </div>
</template>
<script>
export default {
    name: 'goods-detail',
    validate({ params, query }) {
      return typeof params.id === 'number'  
    },
    data() {
        return {
            goodsId: this.$route.params.id,
            a: this.$route.query.a,
            b: this.$route.query.b,
        }
    }
}
</script>

如果params的id参数不是number类型,就不显示页面,如果params参数是number就可以正常显示.
eg:pages/goods/_id.vue

<template>
    <div class="goods" style="background:rgb(152, 152, 254)">
        <h1>商品</h1>
        <nuxt-link to="/goods/1?a=1&b=11">商品01</nuxt-link>
        <nuxt-link to="/goods/2">商品02</nuxt-link>
        <nuxt-link :to="{name:'goods-id', params:{id:3}, query:{a:3,b:33}}">商品03</nuxt-link>
        <nuxt-link to="/goods/comment">评论</nuxt-link>

        <!-- 展示区 -->
        <nuxt/>
    </div>
</template>
 to="/goods/1?a=1&b=11" 这种写法参数就是字符串
:to="{name:'goods-id', params:{id:3}, query:{a:3,b:33}}" 这种写法参数就number类型

点击商品1:
在这里插入图片描述
点击商品3:
在这里插入图片描述

编程式路由跳转

之前使用的<router-link>都是导航式路由跳转,当然也可以使用编程式路跳转。

编程式路由的获取

  • 直接使用组件实例身上的路由对象:this.$route, 在模板中直接使用$route即可——vue2的写法
  • 使用库vue-router,然后使用useRoute()方法获取路由——vue3的写法
<script setup lang="ts">
	const route = useRoute()
	console.log(route.params.id)
</script>

编程式路由的使用

以vue2的写法为例:

this.$router.push()
this.$router.replace()
this.$router.back()
this.$router.forward()
this.$router.go(n)

他们的参数和<nuxt-link :to="">中to的对象写法的参数一样,可以是一个字符串也可以是一个对象

  • push是追加历史记录的路由
  • replace是替换当前记录的路由
  • back() 后退
  • forward() 前进
  • go(n) 前进n步

路由的动态效果

我们可以为所有的路由跳转统一添加一个动态效果:

nuxt全局css的配置

为路由添加全局动态效果就需要我们配置全局的css样式了。

  • 首先在全局资源文件夹assets下创建全局的css文件,如css/index.css
  • 然后在nuxt.config.js下进行配置
css: [
    'assets/css/index.css'
  ],

路由淡入淡出效果

设置路由的样式效果可以直接使用nuxt提供的css样式:page-enter-active,page-leave-active,page-enter

  • assets/css/transition.css:
/* 路由统一动效 */

/* 动画形式 */
.page-enter-active,.page-leave-active{
  transition: opacity .5s;
}

/* 进入和离开页面的样式 */
.page-enter,.page-leave-active{
  opacity: 0;
}
  • nuxt.config.js配置
export default {
...

  /*
  ** 全局样式
  */
  css: [
    'assets/css/transition.css'
  ],
  
...}

效果:
在这里插入图片描述

单个页面的动态效果

nuxt在每一个页面为我们专门提供了一个过渡效果的配置项transitIon, 和data同级,该配置项用来决定当前页面访问的过渡效果。transition的取值需要和对应的样式类名一致:

  • transition的取值是动画名
  • 那么对用的类名的取值就应该是:(既可以写在页面但对应的style标签中,也可以写在全局的css样式中)
/* 单个页面的动态效果 */

/* 动画形式 */
.动画名-enter-active,.动画名-leave-active{
  transition: .5s ease all;
}

/* 进入和离开页面的样式 */
.动画名-enter,.动画名-leave-active{
  margin-left: -1000px;
}

eg:

/pages/goods/_id.vue: (商品详情页)

<template>
  <div style="background: rgb(255, 255, 152)">
    <h2>商品{{ goodsId }}的详情页</h2>
    <h3>携带参数: a:{{ a }},b:{{ b }}</h3>
    <!-- <h4>款式</h4>
        <nuxt-link :to="`/goods/${goodsId}/1`">款式1</nuxt-link>
        <nuxt-link :to="`/goods/${goodsId}/2`">款式2</nuxt-link>
        <nuxt/> -->
    <h4>生产商</h4>
    <nuxt-link :to="`/goods/${goodsId}/producer`">生产商是:</nuxt-link>
    <nuxt />
  </div>
</template>
<script>
export default {
  name: "goods-detail",
  validate({ params, query }) {
    return typeof params.id === "number";
  },
  data() {
    return {
      goodsId: this.$route.params.id,
      a: this.$route.query.a,
      b: this.$route.query.b,
    };
  },
  transition: "test",
};
</script>
<style>
/* 动画形式 */
.test-enter-active,
.test-leave-active {
  transition: 0.5s ease all;
}

/* 进入和离开页面的样式 */
.test-enter,
.test-leave-active {
  margin-left: -1000px;
}
</style>

展示效果是:
在这里插入图片描述

nuxt的路由守卫

前置路由

前置路由主要依赖于中间件middleware插件。根据配置的方式不同可以分为:全局守卫,组件独享守卫。

全局前置守卫

全局卡安置守卫的配置有三种方式:nuxt.config.js中的中间件配置、layouts中的中间件配置、插件配置

1.nuxt.config.js中的中间件配置
nuxt.config.js的配置信息:

export default {
  // 服务端渲染模式,同构
  mode: 'universal',
  ...
  /**
   * 路由配置
   */
  router: {
    middleware: 'auth',
    /**
     * nuxt每次启动都会执行extendRoutes函数
     * @param {*routes} routes 所有路由信息
     * @param {*resolve} resolve 磁盘上的所有函数
     */
    extendRoutes(routes, resolve) {
      console.log('route', routes);
      // 扩展路由
      // 添加路由
      routes.push({
        name: 'home',//路由别名
        path: '/index',//路由路径
        component: resolve(__dirname, 'pages/index.vue')//显示组件
      })

    }
  },
  ...
 }

middleware/auth.js的信息;

/**
 * 接收一个全局上下文参数context
 */
export default ({ store, route, redirect, param, query, req, res }) => {
  // - store: 状态树信息,vuex的相关信息
  // - route:目标路由的信息
  // - redirect:强制跳转
  // - param:param参数信息
  // - query:query参数信息
  // - req:请求的req信息
  // - res:响应的res信息

  // 强跳转到登录页面
  redirect('/login')

  // 全局守卫业务
  console.log("全局前置路由守卫 —— nuxt.config.js")
}

操作结果是无论访问那个路径最后都会跳转到login页面,
控制台和浏览器输出:

全局前置路由守卫 —— nuxt.config.js

2.layouts中的中间件配置
eg:layout/default.vue

<template>
  <div>
    <!-- 跳转区 nuxt-link -->
    <AppHeader></AppHeader>
    <!-- 展示区,相当于routerview -->
    <nuxt />
  </div>
</template>
<script>
import AppHeader from "./app-header.vue";
export default {
  // // layout层级中间件
  // // 1. 引用外部中间件
  // middleware: 'auth',
  // // 2. 使用内部中间件
  middleware({ store, route, redirect, params, query, req, res }) {
    // - store: 状态树信息,vuex的相关信息
    // - route:目标路由的信息
    // - redirect:强制跳转
    // - param:param参数信息
    // - query:query参数信息
    // - req:请求的req信息
    // - res:响应的res信息

    // 强跳转到登录页面
    redirect("/login");

    // 全局守卫业务
    console.log("全局前置路由守卫 —— layouts布局");
  },
  components: { AppHeader },
};
</script>

操作结果是无论访问那个路径最后都会跳转到login页面,
控制台和浏览器输出:

全局前置路由守卫 —— layouts布局

3.插件配置全局前置守卫

  • 插件配置
    plugins的配置和css的配置方式一样:
    (1) 在plugins文件夹下配置对应的插件文件,如:router.js
    (2) 在nuxt.config.js文件中配置plugins信息:
export default {
  // 服务端渲染模式,同构
  mode: 'universal',
  ...
 /*
  ** 全局插件
  */
  plugins: [
    // ~ 表示当前项目的根目录
    '~/plugins/router',
  ],
  ...
 }
  • 插件全局前置路由的配置
    在插件中也可以拿到context上下文,context包含:
- app:vue的app实例
- redirect: 强制跳转
- query
- paraams
- route
- 等等还有很多信息,可以自行打印输出查看

注意:虽然我们可以拿到vue实例,可使用vue实例的router参数的beforeEach方法来进行全局前置路由守卫的设置,但是我们不能使用里面的next方法携带参数进行路由的跳转,如果直接使用next()是允许的,如果想要冲顶下昂到其他页面我们可以使用redirect进行跳转:

在plugins/router.js文件中编写如下内容:

export default ({app, redirect, param,query,store})=>{
  // app: vue实例
  // redirect:强制重定向
  console.log("插件配置——全局路由守卫")
  app.router.beforeEach((to,from, next)=>{
    // next('/login'), next(true), next(false) 不能这样使用,但是可以使用next()
    if(to.name === 'login' || to.name === 'reg'){
      next()
    }else{
      redirect({name:'login'})
    }
  })
}

显示效果是,只有login页面和reg页面可以正常访问,其他页面都是会跳转到login页面。
浏览器和终端输出

插件配置——全局路由守卫

组件独享前置守卫

组件独享前置守卫有两种方式:页面中间件、是由vue提供的beforeRouteEnter钩子
1. 页面中间件配置
pages/user.vue

<template>
  <div class="user">
    <h1>用户中心</h1>
  </div>
</template>
<script>
export default {
  // 页面中间件
  // 1. 引用外部中间件
  // middleware: "auth",
  // 2. 使用内部中间件
  middleware({ store, route, redirect, params, query, req, res }) {
    // - store: 状态树信息,vuex的相关信息
    // - route:目标路由的信息
    // - redirect:强制跳转
    // - param:param参数信息
    // - query:query参数信息
    // - req:请求的req信息
    // - res:响应的res信息

    // 强跳转到登录页面
    redirect("/login");

    // 全局守卫业务
    console.log("组件前置独享守卫 —— 页面布局");
  },
};
</script>

效果是其他页面都可以正常访问,但是访问user页面的时候就会直接跳转到login页面
在这里插入图片描述
浏览器输出

组件前置独享守卫 —— 页面布局

2. beforeRouteEnter钩子使用
vue提供的beforeRouteEnter钩子也可以配置组件的前置路由守卫
pages/reg.vue

<template>
  <div class="reg">
    <h1>注册</h1>
  </div>
</template>
<script>
export default {
  beforeRouteEnter(to, from, next) {
    console.log("路由前置守卫");
    // 允许使用nuxt
    // bl表示确认弹窗的返回值,取值是true或false
    let bl = window.confirm("是否要进入注册页面");
    // next()的参数是true或false,true表示允许离开,false表示不允许离开
    next(bl);
  },
};
</script>

这样访问注册页面的时候都会有确认弹窗,确认的话就进入注册页面,不去确认的话就不跳转。

后置路由

后置路由的配置也分为组件独享后置守卫、 全局后置守卫。

组件独享后置守卫

vue的beforeRouteLeave钩子配置后置路由守卫,beforeRouteLeave的后置守卫是单个页面的路由后置配置。
eg: pages/reg.vue

<template>
  <div class="reg">
    <h1>注册</h1>
  </div>
</template>
<script>
export default {
  beforeRouteLeave(to, from, next) {
    // 允许使用nuxt
    // bl表示确认弹窗的返回值,取值是true或false
    let bl = window.confirm("是否要离开");
    // next()的参数是true或false,true表示允许离开,false表示不允许离开
    next(bl);
  },
};
</script>

离开注册页面的时候会有确认弹窗,如果选择确认就离开,选择否,就不离开当前页面。
在这里插入图片描述
注意:如果使用了beforeRouteEnter或beforeRouteLeave,一定要在钩子中编写next()跳出钩子继续执行,否则就会卡钩子里,不继续执行

全局后置守卫

全局后置守卫可以使用插件配置

  • 在nuxt.config.js中配置插件
  • 使用vue实例的router参数的afterEach方法来进行全局前置路由守卫的设置
    eg:
    pulgins/router.js
export default ({app, redirect, param,query,store})=>{
  // app: vue实例
  // redirect:强制重定向
  // console.log("插件配置——全局路由守卫")
  // app.router.beforeEach((to,from, next)=>{
  //   // next('/login'), next(true), next(false) 不能这样使用,但是可以使用next()
  //   if(to.name === 'login' || to.name === 'reg'){
  //     next()
  //   }else{
  //     redirect({name:'login'})
  //   }
  // })
  app.router.afterEach((to,from)=>{
    console.log("插件配置全局后置守卫")
  })
}

效果:离开每个页面的时候浏览器和控制台都会输出

插件配置全局后置守卫

补充:配置nuxt错误页面

Nuxt都是约定式的,直接在layouts文件夹下编写error.vue页面就可以,错误信息直接使用vue中的props属性进行接受即可,这也是约定好的。

  • 接受error信息:props:['error']
  • error信息的格式:error:{statusCode, message}
    eg:
    layouts/error.vue
<template>
  <div class="error">
    <h1 v-if="error.statusCode">{{ error.message }}</h1>
    <h1 v-else>应用发送异常</h1>
    <!-- <router-link to="/">跳转到home页面</router-link> -->
    <button
      @click="
        () => {
          $router.replace('/index');
        }
      "
    >
      返回首页
    </button>
  </div>
</template>
<script>
export default {
  props: ["error"],
};
</script>
<style scoped>
.error {
  text-align: center;
}
button {
  background: white;
  border: 1px solid black;
  border-radius: 10px;
  padding: 5px 10px;
  font-size: large;
}
button:hover {
  cursor: pointer;
  background: rgb(172, 201, 245);
  border: 1px solid white;
  color: white;
}
</style>

在这里插入图片描述

Nuxt3的路由

nuxt3对应的是vue3,获取方式和vue3是一样的,通过库vue-router,然后使用useRoute()方法获取路由。
eg:

  • 获取params参数:
const route = useRoute()
console.log(route.params.id)
  • 获取query参数:
const route = useRoute()
console.log(route.query.id)
  • 路由跳转:
const route = useRoute()
route.replace("/index")
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐