在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 相关文章推荐
文字幻灯片
Jun 26 Javascript
node在两个div之间移动,用ztree实现
Mar 06 Javascript
jquery $(this).attr $(this).val方法使用介绍
Oct 08 Javascript
JS数组的赋值介绍
Mar 10 Javascript
用file标签实现多图文件上传预览
Feb 14 Javascript
JS中将多个逗号替换为一个逗号的实现代码
Jun 23 Javascript
JavaScript 通过Ajax 动态加载CheckBox复选框
Aug 31 Javascript
微信小程序自定义toast组件的方法详解【含动画】
May 11 Javascript
JavaScript 继承 封装 多态实现及原理详解
Jul 29 Javascript
vue中watch和computed为什么能监听到数据的改变以及不同之处
Dec 27 Javascript
JavaScript实现猜数字游戏
May 20 Javascript
js+css3实现炫酷时钟
Aug 18 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
php防攻击代码升级版
2010/12/29 PHP
JS与PHP向函数传递可变参数的区别实例代码
2011/05/18 PHP
总结PHP如何获取当前主机、域名、网址、路径、端口和参数等
2016/09/09 PHP
PHPCMS V9 添加二级导航的思路详解
2016/10/20 PHP
使用Entrust扩展包在laravel 中实现RBAC的功能
2020/03/16 PHP
Input 特殊事件onpopertychange和oninput
2009/06/17 Javascript
如何确保JavaScript的执行顺序 之jQuery.html并非万能钥匙
2011/03/03 Javascript
js拦截alert对话框另类应用
2013/01/16 Javascript
Enter转换为Tab的小例子(兼容IE,Firefox)
2013/11/14 Javascript
js判断字符长度以及中英文数字等
2013/12/31 Javascript
jquery计算鼠标和指定元素之间距离的方法
2015/06/26 Javascript
jQuery 1.9.1源码分析系列(十三)之位置大小操作
2015/12/02 Javascript
Angular中使用ui router实现系统权限控制及开发遇到问题
2016/09/23 Javascript
JavaScript学习总结之正则的元字符和一些简单的应用
2017/06/30 Javascript
使用form-create动态生成vue自定义组件和嵌套表单组件
2019/01/18 Javascript
详解ECMAScript2019/ES10新属性
2019/12/06 Javascript
Vue中import from的来源及省略后缀与加载文件夹问题
2020/02/09 Javascript
解决vue-pdf查看pdf文件及打印乱码的问题
2020/11/04 Javascript
python分析nignx访问日志脚本分享
2015/02/26 Python
Python实现比较两个列表(list)范围
2015/06/12 Python
Python基于matplotlib实现绘制三维图形功能示例
2018/01/18 Python
Numpy 将二维图像矩阵转换为一维向量的方法
2018/06/05 Python
python框架中flask知识点总结
2018/08/17 Python
python 同时运行多个程序的实例
2019/01/07 Python
详解python中docx库的安装过程
2019/11/08 Python
ffmpeg+Python实现B站MP4格式音频与视频的合并示例代码
2020/10/21 Python
用html5的canvas画布绘制贝塞尔曲线完整代码
2013/08/14 HTML / CSS
梵蒂冈和罗马卡:Omnia Card Pass
2018/02/10 全球购物
美国新娘礼品店:The Paisley Box
2020/09/08 全球购物
怎么写好自荐信
2013/10/30 职场文书
《老王》教学反思
2014/02/23 职场文书
经营管理策划方案
2014/05/22 职场文书
篮球拉拉队口号
2015/12/25 职场文书
高中历史教学反思
2016/02/19 职场文书
调解协议书范本
2016/03/21 职场文书
超级实用的公文标题大全!
2019/07/19 职场文书