在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 相关文章推荐
收藏一些不常用,但是有用的代码
Mar 12 Javascript
基于jquery的二级联动菜单实现代码
Apr 25 Javascript
javascript 文本框水印/占位符(watermark/placeholder)实现方法
Jan 15 Javascript
DOM 中的事件处理介绍
Jan 18 Javascript
js弹出框轻量级插件jquery.boxy使用介绍
Jan 15 Javascript
JS实现侧悬浮浮动实例代码
Nov 29 Javascript
js插件方式打开pdf文件(浏览器pdf插件分享)
Dec 20 Javascript
基于jquery fly插件实现加入购物车抛物线动画效果
Apr 05 Javascript
jQuery单页面文字搜索插件jquery.fullsearch.js的使用方法
Feb 04 jQuery
js实现带积分弹球小游戏
Jul 21 Javascript
原生js实现表格循环滚动
Nov 24 Javascript
TypeScript 使用 Tuple Union 声明函数重载
Apr 07 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
5款适合PHP使用的HTML编辑器推荐
2015/07/03 PHP
PHP编程实现的TCP服务端和客户端功能示例
2018/04/13 PHP
PHP常见加密函数用法示例【crypt与md5】
2019/01/27 PHP
PHP实现Snowflake生成分布式唯一ID的方法示例
2020/08/30 PHP
如果文字过长,则将过长的部分变成省略号显示
2006/06/26 Javascript
jQuery - css() 方法示例详解
2014/01/16 Javascript
javascript自定义的addClass()方法
2014/05/28 Javascript
在myeclipse中如何加入jquery代码提示功能
2014/06/03 Javascript
Javascript Objects详解
2014/09/04 Javascript
node.js中的fs.readFileSync方法使用说明
2014/12/15 Javascript
H5移动端适配 Flexible方案
2016/10/24 Javascript
JS高级运动实例分析
2016/12/20 Javascript
原生js实现中奖信息无间隙滚动效果
2017/01/18 Javascript
Webpack4+Babel7+ES6兼容IE8的实现
2019/04/10 Javascript
解决vue跨域axios异步通信问题
2019/04/17 Javascript
JSON是什么?有哪些优点?JSON和XML的区别?
2019/04/29 Javascript
vue实现的上拉加载更多数据/分页功能示例
2019/05/25 Javascript
Python实现的金山快盘的签到程序
2013/01/17 Python
Python设计模式中单例模式的实现及在Tornado中的应用
2016/03/02 Python
利用Python实现原创工具的Logo与Help
2018/12/03 Python
python中matplotlib条件背景颜色的实现
2019/09/02 Python
Python响应对象text属性乱码解决方案
2020/03/31 Python
python获取响应某个字段值的3种实现方法
2020/04/30 Python
Python依赖包迁移到断网环境操作
2020/07/13 Python
css3 pointer-events 介绍详解
2017/09/18 HTML / CSS
HTML5+CSS3应用详解
2014/02/24 HTML / CSS
英国女性时尚品牌:Apricot
2018/12/04 全球购物
全球速卖通俄罗斯站:AliExpress俄罗斯
2019/06/17 全球购物
教师演讲稿范文
2014/01/08 职场文书
办公室文员工作职责
2014/01/31 职场文书
人力资源管理毕业生自荐信
2014/06/26 职场文书
小兵张嘎观后感
2015/06/03 职场文书
我是特种兵观后感
2015/06/11 职场文书
党员反腐倡廉学习心得体会
2015/08/15 职场文书
丧事答谢词大全
2015/09/30 职场文书
Java实现HTML转为Word的示例代码
2022/06/28 Java/Android