在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 maxlength文本字数限制插件
Apr 16 Javascript
广泛收集的jQuery拖放插件集合
Apr 09 Javascript
jquery选择器排除某个DOM元素的方法(实例演示)
Apr 25 Javascript
简介可以自动完成UI的AngularJS工具angular-smarty
Jun 23 Javascript
javascript生成不重复的随机数
Jul 17 Javascript
javascript实现类似java中getClass()得到对象类名的方法
Jul 27 Javascript
基于JavaScript实现树形下拉框
Aug 10 Javascript
Bootstrap时间选择器datetimepicker和daterangepicker使用实例解析
Sep 17 Javascript
JS变量中有var定义和无var定义的区别以及es6中let命令和const命令
Feb 19 Javascript
Vue响应式添加、修改数组和对象的值
Mar 20 Javascript
浅谈Vue初学之props的驼峰命名
Jul 19 Javascript
使用webpack搭建vue项目实现脚手架功能
Mar 15 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
如何选购合适的收音机
2021/03/01 无线电
SWFUpload与CI不能正确上传识别文件MIME类型解决方法分享
2011/04/18 PHP
php教程 插件机制在PHP中实现方案
2012/11/02 PHP
PHP输出缓冲控制Output Control系列函数详解
2015/07/02 PHP
php foreach如何跳出两层循环(详解)
2016/11/05 PHP
php简单计算权重的方法示例【适合抽奖类应用】
2019/06/10 PHP
利用WebBrowser彻底解决Web打印问题(包括后台打印)
2009/06/22 Javascript
JQuery中的事件及动画用法实例
2015/01/26 Javascript
Node.js与Sails ~项目结构与Mvc实现及日志机制
2015/10/14 Javascript
Angularjs 滚动加载更多数据
2016/03/17 Javascript
JavaScript实现QQ聊天消息展示和评论提交功能
2017/05/22 Javascript
JavaScript 跨域之POST实现方法
2018/05/07 Javascript
微信小程序实现列表页的点赞和取消点赞功能
2018/11/02 Javascript
js操作table中tr的顺序实现上移下移一行的效果
2018/11/22 Javascript
JS+html5实现异步上传图片显示上传文件进度条功能示例
2019/11/09 Javascript
jquery实现上传图片功能
2020/06/29 jQuery
vue+axios 拦截器实现统一token的案例
2020/09/11 Javascript
深入理解python中的atexit模块
2017/03/07 Python
在Python 字典中一键对应多个值的实例
2019/02/03 Python
python使用 __init__初始化操作简单示例
2019/09/26 Python
Tensorflow轻松实现XOR运算的方式
2020/02/03 Python
pandas使用之宽表变窄表的实现
2020/04/12 Python
Python 多线程共享变量的实现示例
2020/04/17 Python
python3爬虫中多线程的优势总结
2020/11/24 Python
Pandas对每个分组应用apply函数的实现
2020/12/13 Python
Web页面中八种创建多列等高(等高列布局)的实现技术
2012/12/24 HTML / CSS
家用个人磨皮机:Trophy Skin
2017/03/30 全球购物
欧洲顶级的童装奢侈品购物网站:Bambini Fashion(面向全球)
2018/04/24 全球购物
波兰补充商店:Muscle Power
2018/10/29 全球购物
C# Debug和Testing相关面试题
2015/10/25 面试题
室内设计专业学生的自我评价分享
2013/11/27 职场文书
家长会学生家长演讲稿
2013/12/29 职场文书
《称象》教学反思
2014/04/25 职场文书
三好学生评选事迹材料(2016精选版)
2016/02/25 职场文书
Python 游戏大作炫酷机甲闯关游戏爆肝数千行代码实现案例进阶
2021/10/16 Python
分析SQL窗口函数之排名窗口函数
2022/04/21 Oracle