vue-router项目实战总结篇


Posted in Javascript onFebruary 11, 2018

今天来谈谈vue项目{vue,vue-router,component}三大神将之一的vue-router。作为我们前后端分离很重要的实践之一,router帮我们完成了SPA应用间的页面跳转。

并且,配合axios这样的第三方库,我们可以实现配合后台接口的拦截器功能。

对于一个小型项目而言,router这个文件夹里面就包含了一个router.js就足够了,

但是,当我们的页面比较多的时候,我们就需要分出两个文件出来:一个定义我们的路由和组件,另一个实例化组件,并将路由挂载到vue的实例上。

基本的用法就不多赘述,大家可以看vue-router的官网,认真过一遍的话,基本使用肯定没什么问题。

1.为什么我的路由不起作用?

这里有个非常重要的一点就是当我们去构造VueRouter的实例的时候,传入的参数的问题。

import routes from '@/router/router'
const router = new VueRouter({
 routes // (ES6语法)相当于 routes: routes
})
new Vue({
 router
}).$mount('#app')

如果你这里引入的不是routes,你就要按照下面的方式来写。

import vRoutes from '@/router/router'
const router = new VueRouter({
 routes :vRoutes 
})
new Vue({
 router
}).$mount('#app')

2.在路由中基于webpack实现组件的懒加载

对于我们的vue项目,我们基本都是运用webpack打包的,如果没有懒加载,打包后的文件将会异常的大,造成首页白屏,延时严重,不利于用户体验,而运用懒加载则可以将页面进行划分,webpack将不同组件打包成很多个小的js文件。需要的时候再异步加载,优化用户的体验,换而言之,有的页面可能100个用户只有一两个会进去,何必把流量花在它身上。

import App from '@/App.vue'
const index = r => require.ensure([], () => r(require('@/pages/index/index')), 'index')
export default [{
 path: '/',
 component: App,
 children: [
  {
    path: '/index',
    name:'index',
    component: index
  }]
}]

 如果某个组件包含了嵌套路由,我们也可以将两个路由打包到一个js chunk中。

// 这两条路由被打包在相同的块中,访问任一路由都会延迟加载该路由组件
const orderUser= r => require.ensure([], () => r(require('@/pages/order/user')), 'order')
const payRecord= r => require.ensure([], () => r(require('@/pages/order/payRecord')), 'order')

3.router的模式

对于浏览器,我们的router分为两种模式。

1.hash模式(默认)

按照一个uri的基本结构来说,hash模式就是在一个基本的URI的片段进行的处理。如果抛开SPA的话,比较常见的应用场景就是我们在做pc商城的时候,会有比如说:商品详情,评论,商品参数这样的tab切换,就可以使用a标签配合id使用,加上一点运动的特效,效果甚佳。

这也是router默认使用的路由方式。不过,这种方式有一个弊端,就是在接入第三方的支付的时候,我们传入一个url给到第三方支付作为回调地址,但是在支付完成以后,有的第三方支付会把我们的#作为一个截取符号,仅保留第一个#符号前面的url内容,后面再添加相应的回调参数。导致支付完成以后无法跳转到相应的支付页面

传入的url:

http://xx.xx.com/#/pay/123

回调后的地址:

http://xx.xx.com/pay/123?data=xxxxx%xxxx 

2.history模式

还有一种就是history的模式。它是使用h5的history.pushState来完成URL的跳转的。使用这种方式来处理跳转的好处就是,url和我们平常看到的没有什么区别。和hash模式作比较的话就是没有了#。不过使用history模式,我们在后台也要去做相应的处理,因为如果直接去访问一个地址,例如http://www.xxxx.com/user/id的时候,如果后端没有配置的时候,后端就会返回404页面。

4.router-link在循环中this.参数名=undefined

<router-link>组件是我们在view层中需要用到的跳转组件。它替代了<a>标签需要做的事情,并且帮助我们做了更多的事情。

无论是 h5 history 模式还是 hash 模式,它的表现行为一致,所以,当你要切换路由模式,或者在 IE9 降级使用 hash 模式,无须任何变动。

在 HTML5 history 模式下,router-link 会守卫点击事件,让浏览器不再重新加载页面。

当你在 HTML5 history 模式下使用 base 选项之后,所有的 to 属性都不需要写(基路径)了。

不过当我们在v-for的循环中使用了router-link的时候,一般来说,我们需要取的都是循环里的值,通过定义的item.xxx就可以取到。如果说需要取一个我们在data中定义的值的时候,我们是通过this.foo来取呢?还是通过foo来取呢?还是都可以?

这里的话,我们是不能通过this.foo来取的,因为这里的this,不再是指向vue的实例了,而是指向了[object Window]。所以用this.foo来取的话,其实是undefined.

<router-link tag="li" :to="{path:`/user/${item.userID}`}" v-for="(item, index) in userList" :key="index">
   //含有固定的值
  <p>{{this.foo}}</p>
  <p>{{foo}}</p>
 </router-link>
data(){
  return {
    foo:'bar',
  } 
}

 4.vue-router配合axios的使用

 初次接触拦截器这个概念是在java中,通过拦截器,我们可以对用户的登录状态进行更加粒度的操作。而对于一个SPA的应用来说,没有了后台路由的介入,我们就需要在前端实现一套自己的登录状态的管理机制。

最直观的一点就是,通过用户的token来判断用户是否登录?

router.beforeEach((to, from, next) => {
 const NOW = new Date().getTime();
 if (to.matched.some(r => r.meta.requireAuth)) {
  if(NOW > store.state.deadLine){
   store.commit('CLEAR_USERTOKEN')
  }
  if (store.state.message.login === true) {
   next();
  }
  else {
   next({
    path: '/login',
    query: {redirect: to.fullPath}
   })
  }
 }
 else {
  next();
 }
})

上面的代码中,我们通过vue-router中的全局守卫,在导航触发的时候大致做了如下几件事:

(1)判断导航的页面是否需要登录

(2)超过登录持久期限,清除持久化的登录用户token

(3)没有超过登录期限,判断是否登录状态

(4)没登录,重定向到登录页面

但是,仅仅这样是不够的。因为用户直接不正常注销而直接后台运行网页是很正常的事情,这就导致虽然token是存在的,但是对于后台而言,这个token是无效的,过期的了。所以,我们需要axios配合后台给出的状态码来完善我们的拦截器。

import router from '@/router/routes'
axios.interceptors.response.use(
 success => {
  switch (success .code) {
   case -100:
    router.replace({
     path: 'login',
     query: {redirect: router.currentRoute.fullPath}
    })
    console.warn('注意,登录已过期!')
    break;
  }
  return success;
 },
 error => {
   switch (error.code) {
    case 404:
     console.warn('请求地址有误或者参数错误!')
    break;
   }
  return Promise.reject(error.response.data)
 });

 通过后端给到的登录过期状态码,这里以-100为例,我们可以用axios的响应拦截器实现,当我们的token过期的时候,我们将页面重定向到登录页面去。

 5.巧用replace替换push

在项目中,我有的同事就是一直this.$router.push(...),从开始push到结尾。

碰到有的页面,比如说,在选择地址的时候需要知道用户当前所在的城市,如果没有的话,就是重定向到城市列表页面去手动选取。选择完成以后再回到选择地址的页面,如果一直使用push的话,点击选择地址的后退时,就会回退到城市列表页。然后造成页面间的死循环。

这里如果使用replace来操作就没有什么问题了,问题就是我们不应该让城市列表页出现在我们的浏览历史里面。

总结

以上所述是小编给大家介绍的vue-router项目实战总结,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
给网站上的广告“加速”显示的方法
Apr 08 Javascript
Extjs学习笔记之二 初识Extjs之Form
Jan 07 Javascript
javascript实现判断鼠标的状态
Jul 10 Javascript
js获取新浪天气接口的实现代码
Jun 06 Javascript
利用JS实现页面删除并重新排序功能
Dec 09 Javascript
jQuery操作json常用方法示例
Jan 04 Javascript
原生js简单实现放大镜特效
May 16 Javascript
Vue2.0实现购物车功能
Jun 05 Javascript
详解Vue.use自定义自己的全局组件
Jun 14 Javascript
JS中offset和匀速动画详解
Feb 06 Javascript
如何在Angular应用中创建包含组件方法示例
Mar 23 Javascript
前端Vue项目详解--初始化及导航栏
Jun 24 Javascript
vue项目实战总结篇
Feb 11 #Javascript
在 Angular中 使用 Lodash 的方法
Feb 11 #Javascript
Material(包括Material Icon)在Angular2中的使用详解
Feb 11 #Javascript
原生JS实现循环Nodelist Dom列表的4种方式示例
Feb 11 #Javascript
Vue实现点击后文字变色切换方法
Feb 11 #Javascript
Vue-cli中为单独页面设置背景色的实现方法
Feb 11 #Javascript
vue刷新和tab切换实例
Feb 11 #Javascript
You might like
php下一个阿拉伯数字转中文数字的函数
2007/07/16 PHP
解析PHP函数array_flip()在重复数组元素删除中的作用
2013/06/27 PHP
PHP file_get_contents函数读取远程数据超时的解决方法
2015/05/13 PHP
PHP获取当前URL路径的处理方法(适用于多条件筛选列表)
2017/02/10 PHP
CI框架(CodeIgniter)操作redis的方法详解
2018/01/25 PHP
不用MOUSEMOVE也能滑动啊
2007/05/23 Javascript
始终在屏幕中间显示Div的代码(css+js)
2011/03/10 Javascript
javascript操作excel生成报表示例
2014/05/08 Javascript
js完整倒计时代码分享
2016/09/18 Javascript
详解AngularJs中$sce与$sceDelegate上下文转义服务
2016/09/21 Javascript
探索Vue.js component内容实现
2016/11/03 Javascript
原生JS实现图片轮播效果
2016/12/26 Javascript
JavaScript字符串对象
2017/01/14 Javascript
vue.js事件处理器是什么
2017/03/20 Javascript
详解vue-cli本地环境API代理设置和解决跨域
2017/09/05 Javascript
vue2.0s中eventBus实现兄弟组件通信的示例代码
2017/10/25 Javascript
nodejs async异步常用函数总结(推荐)
2017/11/17 NodeJs
Bootstrap 中data-[*] 属性的整理
2018/03/13 Javascript
vue-cli配置全局sass、less变量的方法
2019/06/06 Javascript
WEEX环境搭建与入门详解
2019/10/16 Javascript
逐行分析鸿蒙系统的 JavaScript 框架(推荐)
2020/09/17 Javascript
jQuery插件实现图片轮播效果
2020/10/19 jQuery
[00:20]TI9不朽观赛名额抽取
2019/08/05 DOTA
python通过shutil实现快速文件复制的方法
2015/03/14 Python
Python实现简单查找最长子串功能示例
2019/02/26 Python
Python集合基本概念与相关操作实例分析
2019/10/30 Python
Jack Rogers官网:美国经典的女性鞋靴品牌
2019/09/04 全球购物
如何用Java实现列出某个目录下的所有子目录
2015/07/20 面试题
物业经理求职自我评价
2013/09/22 职场文书
电子商务专业推荐信范文
2013/12/02 职场文书
实验教师岗位职责
2014/02/13 职场文书
酒店行政人事部经理职务说明书
2014/02/26 职场文书
老干部工作先进事迹
2014/08/17 职场文书
大一新生期末自我评价
2014/09/12 职场文书
运动会广播稿200字
2014/10/18 职场文书
Nginx Rewrite使用场景及配置方法解析
2021/04/01 Servers