vue-router原理

1 篇文章 0 订阅
1 篇文章 0 订阅

弄清vue-router大概原理可从以下3个问题出发

  1. 如何监听url变化
  2. vue插件使用,以及Vue.use(VueRouter)做了什么
  3. 如何渲染当前匹配组件

如何监听url变化

首先我们要知道前端路由,前端路由、后端路由都是一种相对概念,就是为了区分而起了个名字,就好比客户端渲染和服务端渲染,他们都是成对出现的,在没有客户端渲染的时候应该没人会把从服务器获取完整的html文档叫服务端渲染把,前端路由也是如此。

前端路由的特点就是,相对后端路由,改变url,页面无需刷新。

前端路由有两种实现方式,hash模式和h5 history模式

hash模式

通过改变url # 后面的内容来改变url,可用window.location.hash改变hash值,利用window.onhashchange来监听hash变化

history模式

相对hash更灵活,没有只能修改#后面的内容的限制,可利用pushState和replaceState来改变url,利用window.onpopstate来监听url变化

详见mdn history api

vue插件使用

知道了怎么跳转及监听url变化,现在需要利用插件和vue结合起来

Vue.use

why use Vue.use? 在模块化环境下,插件里是没有Vue的,所以得有一个机制把Vue作为参数传入,就是Vue.use。

为啥不在插件import Vue from 'vue'而是通过参数传入Vue呢,个人理解

  1. 写插件时,不应该和外部环境耦合,造成代码侵入
  2. 代码单元测试时不一定需要用到vue,如果没有安装vue,造成报错
  3. 如果每个插件都去安装一遍vue,太浪费了
  4. 实在不雅

通过Vue.use安装了插件,并调用install方法,这时做了什么?

既然use是为了拿到Vue,那么肯定就是要用它,且看看删减版源码

function install (Vue) {
    // 1
    Vue.mixin({
      beforeCreate: function beforeCreate () {
        if (isDef(this.$options.router)) { // 对new Vue({router:router})你应该有印象,这里说明有router就是根实例
          this._routerRoot = this;
          this._router = this.$options.router;
          this._router.init(this); //调用init方法,主要是处理首次进入和设置url变化监听
          Vue.util.defineReactive(this, '_route', this._router.history.current); // 把_route属性变为响应式的,后面只需要改变_route就会触发更新
        } else { // 否则就从父组件的找
          this._routerRoot = (this.$parent && this.$parent._routerRoot) || this;
        }
      },
    });

   // 2
    Object.defineProperty(Vue.prototype, '$router', { // 方便 this.$router使用
      get: function get () { return this._routerRoot._router }
    });

    Object.defineProperty(Vue.prototype, '$route', {// 方便 this.$route使用
      get: function get () { return this._routerRoot._route }
    });
    // 3
    Vue.component('RouterView', View); // 注册router-view组件
    Vue.component('RouterLink', Link); // 注册router-link

  }

 

这里很重要的一点就是Vue.util.defineReactive(this, '_route', this._router.history.current),当监听到url变化,我们把url赋给_route,这样就触发了组件更新

    history.listen(function (route) {
      this$1.apps.forEach(function (app) {
        app._route = route;
      });
    });

如何渲染当前匹配组件

首先是根据当前route去匹配对应的组件,然后就是router-view去渲染对应的组件

关于router-view,你可能会很好奇,它是怎么实现动态切换组件的,我一开始以为是v-if,v-else-if什么的,但是感觉太low了吧,所以这个组件用template显然不合理,那么就得用到 render函数 了, 实现灵活的动态渲染。

 

// 源码中router-view render函数并非这样,这里只做原理解释
function render(createElement){
    return createElement(matchedCoponent)
}

 

不得不说,vue用起来简单,但想要用好,首先一定要多了解文档,然后就是看个人如何灵活运用了。看源码也挺重要,但是需要一定要带着问题看,非相关代码一律按纸老虎处理,否则会看的很迷

总结一下vue-router原理

  • 前端路由实现页面不刷新,有hash和history模式,通过onhashchange或onpopstate来监听url变化
  • Vue.use使用VueRouter,传入Vue,通过混入在beforeCreate做了一些route的定义和调用Vue.util.defineReactive使之变成响应式,使的url变化时可以触发组件更新
  • 在Vue原型定义了$router和$route,注册了router-view和router-link组件
  • router-view是通过编写render函数,而非template,来实现动态渲染的

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值