欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

vue-router原理

程序员文章站 2022-08-17 09:35:59
弄清vue-router大概原理可从以下3个问题出发如何监听url变化vue插件使用,以及Vue.use(VueRouter)做了什么url变化如何通知组件更新如何监听url变化首先我们要知道前端路由,前端路由、后端路由都是一种相对概念,就是为了区分而起了个名字,就好比客户端渲染和服务端渲染,他们都是成对出现的,在没有客户端渲染的时候应该没人会把从服务器获取完整的html文档叫服务端渲染把,前端路由也是如此。前端路由的特点就是,相对后端路由,改变url,页面无需刷新。前端路由有两种...

弄清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

vue-router原理

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

vue-router原理

为啥不在插件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函数 了, 实现灵活的动态渲染。

 

vue-router原理

// 源码中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,来实现动态渲染的

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

本文地址:https://blog.csdn.net/illusion_melody/article/details/109368237