在nuxt中使用路由重定向的实例


Posted in Javascript onNovember 06, 2020

我们都知道,在写SPA的时候,我们可以通过配置vue-router来实现路由的重定向。

官方文档(以及ts类型)的定义中给出了这一选项:

interface RouteConfig = {
 path: string,
 redirect?: string | Location | Function,
}

也就是说,我们可以定义这样一个路由:

{
  path: "/foo",
  redirect: "/foo/bar",
}

这样,我们在访问/foo的时候,就会被重定向到/foo/bar。这些都是老生常谈了。

然而,到了SSR的环境下,如果使用nuxt,因为nuxt采用了约定大于配置的方式,pages目录代替了路由,虽然简化了配置,但是给一些需要定制化的场景的手动配置带来了一些麻烦,并且nuxt官方也不建议手动配置router,如果实在需要配置,可以在nuxt.config.js里进行一些中间件配置,但是这个对于重定向这种特别简单的事情来说,未免有杀鸡用牛刀之嫌。

所以,我一开始想的办法是,在pages目录下,需要重定向的路由组件里,增加一个beforeCreate()钩子:

<template>
 <div></div>
</template>

<script>
export default {
 beforeCreate() {
  this.$router.replace('/path/to')
 }
}
</script>

相当于在组件创建之前进行一个路由的替换,这个组件作为路由的占位。之所以不用push而是用replace,因为replace更接近重定向的效果,我们总不希望用户还能回退(比如浏览器的后退键)到重定向之前的页面里去吧。

但是这个方案有一个问题,就是在路由“重定向”的过程中,界面会发生轻微的闪烁,这样体验就很不好了。所以,肯定需要其他的解决方案。

至于为什么会闪屏,因为虽然beforeCreate钩子理论上会先于模板编译执行,但是这是在SFC环境下,模板编译会提前执行;如果是用script标签引入的Vue就不会有这个问题:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <script src="https://unpkg.com/vue@2.6.11/dist/vue.js"></script>
  <script src="https://unpkg.com/vue-router@3.1.6/dist/vue-router.js"></script>
</head>
<body>
<div id="app">
  <router-view/>
</div>

<script>
  const Foo = {template: '<div>foo</div>'};
  const Bar = {template: '<div>bar</div>'};

  const routes = [
    {path: '/foo', component: Foo, redirect: '/bar'},
    {path: '/bar', component: Bar}
  ];

  const router = new VueRouter({routes});

  const app = new Vue({
    el: '#app',
    router
  })
</script>
</body>
</html>

如果有需要,可以进一步参考Vue官方的生命周期图示。

查了一下文档,好在nuxt提供了这么一个重定向的API,就藏在context对象里。事实上,下面所有的解决方案,都是基于这个context对象进行的:

属性字段 类型 可用 描述
redirect Function 客户端 & 服务端 用这个方法重定向用户请求到另一个路由。状态码在服务端被使用,默认 302 redirect([status,] path [, query])

同时,我们还知道:

asyncData方法会在组件(限于页面组件)每次加载之前被调用。它可以在服务端或路由更新之前被调用。在这个方法被调用的时候,第一个参数被设定为当前页面的上下文对象,你可以利用 asyncData方法来获取数据并返回给当前组件。

所以,我们可以这么写:

<template>
 <div></div>
</template>

<script>
export default {
 asyncData({ redirect }) {
  redirect('/path/to')
 }
}
</script>

这样就可以解决问题了。可能你会想为什么不用fetch来进行路由跳转,因为fetch是用来处理vuex store的数据的,我个人认为从语义上不适合处理路由跳转的任务;当然,实际上是可以正常运行的,反正都是基于context对象进行的操作。

如果你对上面那个空的div感到不满意,觉得不优雅,你也可以搞得更极端一点,使用渲染函数来渲染模板的根节点:

<script>
export default {
 asyncData({ redirect }) {
  redirect('/path/to')
 },
 render(h) {
  return h('div')
 }
}
</script>

这样看起来可能更简洁一点。

但是这种写法对于路由鉴权那种场景是不太适用的。比如,我需要在进行路由跳转前验证用户的身份,我总不能在每个page里都写这么一段吧,维护起来也不方便,如果路由改了,每个页面都得改。

所以,这个时候就得用到nuxt提供的中间件机制了。中间件可以在page层面配置,也可以全局配置,参考官方的例子:

pages/secret.vue

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

<script>
export default {
 middleware: 'authenticated'
}
</script>

middleware/authenticated.js

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

这个也放到nuxt.config.js里,变成全局的配置:

module.exports = {
 router: {
  middleware: 'authenticated'
 }
}

但是有一点需要注意,也是只要使用路由就需要注意的一个问题:避免循环重定向。这和避免写死循环是一个道理。

总结一下:

如果是少数几个页面之间的固定的重定向逻辑,可以直接用asyncData(或者fetch,虽然我个人觉得语义不好)参数里context的redirect来进行重定向;

如果需要重定向的页面数量较多(可以考虑使用中间件 + 表驱动),或者存在一些动态变化的重定向逻辑(比如路由鉴权),可以考虑使用中间件机制。

补充知识:使用Nuxt.js和Vue-i18n重定向到同一页面但切换语言URL

公司最近提出一个需求,就是当用户切换语言的时候,在路由中需要将其选中的语言加入到路由中

例如网址:

localhost/about

应该通过该方法(通过按特定按钮)重定向到:

localhost/bg/about

Nuxt文档中所建议的,用于使用Vue-i18n进行本地化https://nuxtjs.org/examples/i18n/

在 Nuxt 官网中也给出了国际化的例子,但是并不满足公司的这个需求,大家有兴趣可以去看下

Nuxt 官网 国际化的例子

在 components文件夹下面新建 LangSelect.vue文件

<template>
 <el-dropdown trigger="click" class="international" @command="handleSetLanguage">
  <div>
   <i class="el-icon-share">{{$t('home.changelang')}}</i>
  </div>
  <el-dropdown-menu slot="dropdown">
   <el-dropdown-item :disabled="language==='zh'" command="zh">中文</el-dropdown-item>
   <el-dropdown-item :disabled="language==='en'" command="en">English</el-dropdown-item>
  </el-dropdown-menu>
 </el-dropdown>
</template>

<script>
export default {
 computed: {
  language() {
   return this.$store.state.locale;
  }
 },
 methods: {
  handleSetLanguage(language) {
   this.$i18n.locale = language;
   console.log(this.$i18n.locale);
   this.$store.commit("SET_LANG", language);
  //  console.log(this.$store.state.locale, "locale");
   var beforePath = this.$nuxt.$router.history.current.path;
   // -- Removing the previous locale from the url
   var changePath = this.$store.state.locale
   var result = "";
   result = beforePath.replace("/en", "");
   result = result.replace("/zh", "");
  this.$nuxt.$router.replace({ path: "/" + changePath + result });
   this.$message({
    message: "Switch Language Success",
    type: "success"
   });
  }
 }

};
</script>

在middleware文件中新建i18n.js

export default function ({ isHMR, app, store, route, params, error, redirect }) {
  const defaultLocale = app.i18n.fallbackLocale
  // If middleware is called from hot module replacement, ignore it
  //如果从热模块替换调用中间件,请忽略它
  if (isHMR) { return }
  // Get locale from params
  const locale = params.lang || defaultLocale
  if (!store.state.locales.includes(locale)) {
   return error({ message: 'This page could not be found.', statusCode: 404 })
  }
  // Set locale
  store.commit('SET_LANG', locale)
  app.i18n.locale = store.state.locale

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

其他的配置都可以在 上面给出的官网链接中找到,这里就不在重复了。

以上这篇在nuxt中使用路由重定向的实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
跟我一起学写jQuery插件开发方法(附完整实例及下载)
Apr 01 Javascript
将string解析为json的几种方式小结
Nov 11 Javascript
js实现日期级联效果
Jan 23 Javascript
简述Matlab中size()函数的用法
Mar 20 Javascript
JS获取年月日时分秒的方法分析
Nov 28 Javascript
JavaScript 输出显示内容(document.write、alert、innerHTML、console.log)
Dec 14 Javascript
vue2实现可复用的轮播图carousel组件详解
Nov 27 Javascript
使用 Vue 绑定单个或多个 Class 名的实例代码
Jan 08 Javascript
vue小白入门教程
Apr 02 Javascript
JavaScript实现百度搜索框效果
Mar 26 Javascript
JS阻止事件冒泡的方法详解
Aug 26 Javascript
一文搞懂redux在react中的初步用法
Jun 09 Javascript
Nuxt.js的路由跳转操作(页面跳转nuxt-link)
Nov 06 #Javascript
Nuxt的路由配置和参数传递方式
Nov 06 #Javascript
nginx配置域名后的二级目录访问不同项目的配置操作
Nov 06 #Javascript
Jquery Fade用法详解
Nov 06 #jQuery
nuxt静态部署打包相对路径操作
Nov 06 #Javascript
全网小程序接口请求封装实例代码
Nov 06 #Javascript
微信小程序实现自定义动画弹框/提示框的方法实例
Nov 06 #Javascript
You might like
CI框架学习笔记(一) - 环境安装、基本术语和框架流程
2014/10/26 PHP
php上传中文文件名乱码问题处理方案
2015/02/03 PHP
Laravel最佳分割路由文件(routes.php)的方式
2016/08/04 PHP
PHP实现接收二进制流转换成图片的方法
2017/01/10 PHP
PHP实现无限极分类的两种方式示例【递归和引用方式】
2019/03/25 PHP
php连接mysql之mysql_connect()与mysqli_connect()的区别
2020/07/19 PHP
Add a Picture to a Microsoft Word Document
2007/06/15 Javascript
最新28个很棒的jQuery 教程
2011/05/28 Javascript
使表格的标题列可左右拉伸jquery插件封装
2014/11/24 Javascript
JavaScript实现简单的二级导航菜单实例
2015/04/15 Javascript
javascript日期格式化方法小结
2015/12/17 Javascript
原生js封装二级城市下拉列表的实现代码
2016/06/16 Javascript
详解利用 Express 托管静态文件的方法
2017/09/18 Javascript
微信小程序实现天气预报功能
2018/07/18 Javascript
Angular2实现的秒表及改良版示例
2019/05/10 Javascript
vue实现滑动超出指定距离回顶部功能
2019/07/31 Javascript
小程序实现日历左右滑动效果
2019/10/21 Javascript
JS实现进度条动态加载特效
2020/03/25 Javascript
[43:41]VP vs RNG 2019国际邀请赛淘汰赛 败者组 BO3 第二场 8.21.mp4
2020/07/19 DOTA
Python实现Dijkstra算法
2018/10/17 Python
django 单表操作实例详解
2019/07/30 Python
Python常用模块os.path之文件及路径操作方法
2019/12/03 Python
pycharm中选中一个单词替换所有重复单词的实现方法
2020/11/17 Python
matplotlib相关系统目录获取方式小结
2021/02/03 Python
浅谈CSS3 动画卡顿解决方案
2019/01/02 HTML / CSS
html5新特性与用法大全
2018/09/13 HTML / CSS
曼联官方网上商店:Manchester United Direct
2017/07/28 全球购物
星空联盟C# .net笔试题
2014/12/05 面试题
总经理助理岗位职责
2013/11/08 职场文书
合伙协议书范本
2014/04/21 职场文书
社区矫正工作方案
2014/06/04 职场文书
公共场所禁烟倡议书
2014/08/30 职场文书
《我是什么》教学反思
2016/02/16 职场文书
PHP 技巧 * SVG 保存为图片(分享图生成)
2021/04/02 PHP
生命的关键成分来自太空?陨石说是的
2022/04/29 数码科技
Web应用开发TypeScript使用详解
2022/05/25 Javascript