vue-router的使用 & vue-router原理

概念

路由器 router,整个应用共用一个路由器属性$router
路由 route,每个路由组件都有独立的路由属性$route
普通组件:路由没配置的组件
路由组件:路由配置的组件

标签

<router-link class="" to="/path" ></router-link> 默认会被渲染成一个a标签,阻止默认页面跳转行为。
to还可以传对象,包装path、name、params、query等,具体可以参考文档。

<router-view></router-view>路由组件会被渲染到这里

目录结构

普通组件放在components目录中
路由组件放在pages目录中

路由导航

除了上述提到的标签式路由导航,还有编程式路由导航。
例如:

this.$router.push({path:'/user/detail', query:{...}})
this.$router.replace({path:'/user/detail', query:{...}})

push比较适合大的分类路由切换,基本就是切换业务场景了
replace比较适合细小的路由切换,比如当前业务场景下的子品类切换等
这样回退的时候可以一次回到上一个业务场景页面

路由组件

路由切换的时候,路由组件会被挂载,之前的路由组件默认会被销毁。可以用<keep-alive>包裹路由组件,缓存替代销毁。

路由组件获取值的方式:

  1. 组件内直接this.$route.query获取
  2. 组件内直接this.$route.params获取
  3. 比较推荐的是query传参,路由路径配置比较清晰,然后通过配置路由对象内的props属性,给路由组件以props形式传参
// 子路由配置中
children[
 {
   name: 'aaa',
   path: 'detail', // 子路由路径开头不要加“/”
   component: Detail,
   props($route) {
     return { id: $route.query.id, title: $route.query.title }
   }
 }
]

对应的路由组件Detail只需要配置下props:['id', 'title']就可以在模板中方便使用了。
这样写的优点是路由配置相关都集中在一起,组件编码获取参数也不需要获取$route,各自分工明确,聚合性比较好。

利用缓存

<!--name属性指定的是组件名,指定缓存内容区的某个组件-->
<keep-alive name="formItemName">
  <router-view></router-view>
</keep-alive>

使用keep-alive比较适合类似表单页签切换的场景,再配合$router.replace(),可以提高用户体验。

生命周期钩子:actived 和 deactived

actived:被 keep-alive 缓存的组件激活时调用。
deactived:被 keep-alive 缓存的组件失活时调用。

以上2个钩子需要配合keepalive标签使用。如果被缓存的组件已经隐藏了,有些行为例如setInterval等timer计时器的行为(或者其他定制业务行为)并不需要继续执行,可以考虑在actived和deactived钩子中加以控制。

actived() {
  this.timer = setInterval(() => {
    // ...
  })
},
deactived() {
  clearInterval(this.timer)
}

路由导航守卫

以下是路由守卫触发全流程,可以根据业务需求配置。

  1. 导航被触发。
  2. 在失活的组件里调用 beforeRouteLeave 守卫。
  3. 调用全局的 beforeEach 守卫。(router上配置)
  4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  5. 路由配置里调用 beforeEnter。
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter。
  8. 调用全局的 beforeResolve 守卫 (2.5+)。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

浏览器hash模式和history模式

hash模式的地址栏会有一个”#“,后面跟各种路由路径和参数,此模式下浏览器不会将”#“和之后的内容发给服务器,也就是服务收到的请求地址只是”#“之前的部分。

因此如果前端使用了history模式,还想正常访问页面,就得需要后端(或者nginx)对请求的地址进行拦截处理。
例如nodejs可以npm安装connect-history-api-fallback

// 服务端项目
npm install connect-history-api-fallback

服务端处理请求代码(nodejs express)

const express = require('express')
const histroy = require('connect-history-api-fallback')

const app = express() // 创建一个服务
app.use(history()) // 注册history插件,可以根据history规则拆分请求地址
app.use(express.static(__dirname+'/static')) // 注册静态资源地址,这样就可以到前端页面了

// 配置接口
app.get('/user', (req, res) => {
  req.send({
    id: '001',
    name: 'zhangsan'
  })
})

app.listen(5000, err => {
if (!err) console.log('服务启动成功,端口:5000')
})

除了nodejs,我们还可以使用nginx进行反向代理,需要自己配置好正则规则
还可以使用java,也有专门的库支持history模式地址截取。

hash和history相比,hash的兼容性略好一点。vue-router默认使用的是”hash“模式,如果想改成history模式,需要把router的mode配置改成”history“。

vue-router的原理

理论基础
浏览器地址的改变会触发popstate事件;浏览器地址hash(#后面的部分)的改变会触发hashchange事件。这让我们可以监控到当前路由的变化;

调用浏览器的api pushState或者js直接改变location.hash并不会触发页面跳转,只是地址栏地址发生了变化,这让我们可以实现api让浏览器地址改变。

基于上述特性,VueRouter向Vue注入组件后,就可以实现根据路由变化让Vue重新加载指定组件了。这就是所谓的路由跳转。

  1. 一是根据配置的模式(hash还是history)给window加事件监听(popstate或者hashchange)


    html5.js

    hash.js
  2. 使用vue插件+mixin的方式,在beforeCreate()钩子里,往VueComponent实例上加了一个_route属性,用于存放当前路由对象,并且对此属性加了数据代理,地址变化会同步这里的属性。


    index.js

    install.js
  3. RouterView组件发现当前路由改变的时候(通过vue的数据代理),就会根据配置去加载指定的vueComponent从而实现了界面切换效果

router文档
routerAPI文档

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,657评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,889评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,057评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,509评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,562评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,443评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,251评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,129评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,561评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,779评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,902评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,621评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,220评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,838评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,971评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,025评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,843评论 2 354

推荐阅读更多精彩内容