博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
前端vue的路由实现原理
阅读量:5954 次
发布时间:2019-06-19

本文共 4175 字,大约阅读时间需要 13 分钟。

前言

路由最初是由后端提出,浏览器发出请求,服务器根据路由的配置,返回相应信息。后来随着ajax的流行,异步数据请求交互在浏览器局部刷新。单页面更是把这种方式用到了极致,不仅仅是在页面交互是无刷新的,连页面跳转都是无刷新的,本文就从源码来分析下 Vue路由vue-router的实现原理。

1.导入插件

import Router from 'vue-router'    export default class VueRouter {        static install: () => void;       static version: string;       ...} 复制代码

通过import导入的插件是一个VueRouter类。

2.路由注册

Vue.use(Router)

通过Vue.use方法对路由做一个注册,把导入的插件传进去,和Vue关联起来。这个方法会调用plugin来执行插件的install方法,所以一般写插件都会有一个install方法,install方法里,利用Vue.mixin方法给每一个组件注入钩子函数beforeCreate和destroyed前者获得路由实例,初始化路由配置。同时内置全局RouterView和RouterLink两个组件。

源码分析:

export function install (Vue) {//判断install方法是否调用一次  if (install.installed && _Vue === Vue) return  install.installed = true  _Vue = Vue  const isDef = v => v !== undefined  const registerInstance = (vm, callVal) => {    let i = vm.$options._parentVnode    if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {      i(vm, callVal)    }  }//给全局组件注入beforeCreate和destoryed钩子函数,Vue实例创建时,会执行  Vue.mixin({    beforeCreate () {    //判断有无router实例      if (isDef(this.$options.router)) {        this._routerRoot = this        this._router = this.$options.router        //路由初始化,会调用transitionTo做路径切换,        this._router.init(this)        Vue.util.defineReactive(this, '_route', this._router.history.current)      } else {        this._routerRoot = (this.$parent && this.$parent._routerRoot) || this      }      registerInstance(this, this)    },    destroyed () {      registerInstance(this)    }  })  //在原型上创建$router(为一个vueRouter实例,可以调用.push,.go等方法)//$route(为当前路由跳转对象可以获取name、path、query等)两个属性,//方便全局调用  Object.defineProperty(Vue.prototype, '$router', {    get () { return this._routerRoot._router }  })  Object.defineProperty(Vue.prototype, '$route', {    get () { return this._routerRoot._route }  })  // 全局注册组件 router-link(路由跳转) 和 router-view(路由对应组件内容展示)  Vue.component('RouterView', View)  Vue.component('RouterLink', Link)  const strats = Vue.config.optionMergeStrategies  // use the same hook merging strategy for route hooks  strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created}复制代码

3.vueRouter对象

const route = new Router({ routes: [   {     path: '/helloword',redirect: '/welcome' ,     name: 'HelloWorld',     component: HelloWorld,   },   {     path: '/home',     name: 'Home',     component: Home,     children: [       {         path: 'child1',         name: 'Child',         component: Child       }     ]   }, ]})复制代码

new Router时产生这个类的一个实例,路由初始化是在组件初始化阶段,调用beforeCreate钩子函数,执行router.init()初始化路由

源码分析:

var VueRouter = function VueRouter (options) {  if ( options === void 0 ) options = {};    ...  //匹配路由对象  this.matcher = createMatcher(options.routes || [], this);//根据mode采用不同的路由方式,默认hash //共有三种模式history('/地址',需要服务器设置),hash('#地址'),abstract(非浏览器环境使用)  var mode = options.mode || 'hash';  this.fallback = mode === 'history' && !supportsPushState && options.fallback !== false;  if (this.fallback) {    mode = 'hash';  }  if (!inBrowser) {    mode = 'abstract';  }  this.mode = mode;  switch (mode) {    case 'history':      this.history = new HTML5History(this, options.base);      break    case 'hash':      this.history = new HashHistory(this, options.base, this.fallback);      break    case 'abstract':      this.history = new AbstractHistory(this, options.base);      break    default:      {        assert(false, ("invalid mode: " + mode));      }  }};init (app: any /* Vue component instance */) {    process.env.NODE_ENV !== 'production' && assert(      install.installed,      `not installed. Make sure to call \`Vue.use(VueRouter)\` ` +      `before creating root instance.`    )    //添加路由实例    this.apps.push(app)    // main app already initialized.    //确保路由多次添加    if (this.app) {      return    }    this.app = app    const history = this.history    if (history instanceof HTML5History) {      history.transitionTo(history.getCurrentLocation())    } else if (history instanceof HashHistory) {      const setupHashListener = () => {        history.setupListeners()      }      //使用transitionTo完成路径切换      history.transitionTo(        history.getCurrentLocation(),        setupHashListener,        setupHashListener      )    }  }复制代码

...未完待续

转载地址:http://tilxx.baihongyu.com/

你可能感兴趣的文章
20181207 上课截图
查看>>
程序员晒追女神聊天截图,坦言第一次没经验,网友直呼凭实力单身
查看>>
再有人问你Netty是什么,就把这篇文章发给他
查看>>
git 实践之冲突管理
查看>>
centos7安装kibana5.x
查看>>
svn常用命令
查看>>
OSChina 周五乱弹 —— 你用学习机来搞学习?
查看>>
利于前台开发的两大工具flex和vue
查看>>
Error creating bean with name 'userServiceImpl': Injection of autowired dependencies failed
查看>>
mybatis update返回值的意义
查看>>
SVNQuery–如何创建更新索引并查询
查看>>
【开源】.Net Api开放接口文档网站
查看>>
spring整合ehcache
查看>>
《Spring Boot实战》读书笔记
查看>>
molicode生成vue增删改查功能
查看>>
类与类加载器---《深入理解java虚拟机》
查看>>
Magento(CE1.X)自带模块解析一
查看>>
鸟哥Linux私房菜_基础篇(第二版)_第十章学习笔记
查看>>
Hibernate 对c3p0配置不支持导致的错误
查看>>
安装与卸载软件的方法:rpm、yum工具介绍
查看>>