Open mario-mui opened 5 years ago
ps 当前源码commit vue-router 提供了三种运行模式:
<script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <div id="app"> <h1>Hello App!</h1> <p> <router-link to="/foo">Go to Foo</router-link> <router-link to="/bar">Go to Bar</router-link> </p> <router-view></router-view> <script> const Foo = { template: '<div>foo</div>' } const Bar = { template: '<div>bar</div>' } const routes = [ { path: '/foo', component: Foo }, { path: '/bar', component: Bar } ] const router = new VueRouter({ routes }) const app = new Vue({ router }).$mount('#app') </script> </div>
主要这里定义了 router 的各种熟悉。常见的如大家所知
//比如设置mode 为 'history' 默认情况为hash(本文所说的模式), 设置 routes熟悉 options: RouterOptions; //vue-router 实现的三种模式 mode: string; history: HashHistory | HTML5History | AbstractHistory; // 匹配路由的matcher matcher: Matcher; fallback: boolean; // 各种钩子方法 beforeHooks: Array<?NavigationGuard>; resolveHooks: Array<?NavigationGuard>; afterHooks: Array<?AfterNavigationHook>;
默认浏览器下会自动安装 router 地址
<router-link> 和 <router-view>
当我们点击时
const handler = e => { if (guardEvent(e)) { if (this.replace) { router.replace(location) } else { router.push(location) } } } const on = { click: guardEvent } if (Array.isArray(this.event)) { this.event.forEach(e => { on[e] = handler }) } else { on[this.event] = handler // this.event 默认为click }
[源码](https://github.com/vuejs/vue-router/blob/dev/src/components/link.js#L75) 会触发 [router.push ](https://github.com/vuejs/vue-router/blob/dev/src/components/link.js#L66) [router就是](https://github.com/vuejs/vue-router/blob/dev/src/install.js#L38)
push (location: RawLocation, onComplete?: Function, onAbort?: Function) { this.history.push(location, onComplete, onAbort) }
[源码](https://github.com/vuejs/vue-router/blob/dev/src/index.js#L153) 当前history 咱们是默认的hash 模式
push (location: RawLocation, onComplete?: Function, onAbort?: Function) { const { current: fromRoute } = this this.transitionTo(location, route => { pushHash(route.fullPath) handleScroll(this.router, route, fromRoute, false) onComplete && onComplete(route) }, onAbort) }
[源码](https://github.com/vuejs/vue-router/blob/dev/src/history/hash.js#L47)
transitionTo (location: RawLocation, onComplete?: Function, onAbort?: Function) { const route = this.router.match(location, this.current) this.confirmTransition(route, () => { this.updateRoute(route) onComplete && onComplete(route) this.ensureURL()
// fire ready cbs once if (!this.ready) { this.ready = true this.readyCbs.forEach(cb => { cb(route) }) } }, err => { if (onAbort) { onAbort(err) } if (err && !this.ready) { this.ready = true this.readyErrorCbs.forEach(cb => { cb(err) }) } })
}
[源码](https://github.com/vuejs/vue-router/blob/dev/src/history/base.js#L64) 会走调到 this.updateRoute(route)
updateRoute (route: Route) { const prev = this.current this.current = route this.cb && this.cb(route) this.router.afterHooks.forEach(hook => { hook && hook(route, prev) }) }
其中将会调用 `this.cb(route)` this.cb 是什么时候设置的呢。
history.listen(route => { this.apps.forEach((app) => { app._route = route }) })
[源码](https://github.com/vuejs/vue-router/blob/dev/src/index.js#L126-L130) 会去设置 app._route, 我们知道 app._route 是响应式的。会触发 render 函数。从而触发 router-view 的[render行数](https://github.com/vuejs/vue-router/blob/dev/src/components/view.js#L13) 最后回去创建[comment](https://github.com/vuejs/vue-router/blob/dev/src/components/view.js#L54) 然后就是vue 的re-render 从而达到router 的效果
路由模式
ps 当前源码commit vue-router 提供了三种运行模式:
官网的例子来看看vue-router 如何运作的
class VueRouter
主要这里定义了 router 的各种熟悉。常见的如大家所知
vue.install(VueRouter)
默认浏览器下会自动安装 router 地址
<router-link> 和 <router-view>
这两个组件的作用大家在使用时候相信已经知道了。接下来我们要说的是如何点击当我们点击时
push (location: RawLocation, onComplete?: Function, onAbort?: Function) { this.history.push(location, onComplete, onAbort) }
push (location: RawLocation, onComplete?: Function, onAbort?: Function) { const { current: fromRoute } = this this.transitionTo(location, route => { pushHash(route.fullPath) handleScroll(this.router, route, fromRoute, false) onComplete && onComplete(route) }, onAbort) }
transitionTo (location: RawLocation, onComplete?: Function, onAbort?: Function) { const route = this.router.match(location, this.current) this.confirmTransition(route, () => { this.updateRoute(route) onComplete && onComplete(route) this.ensureURL()
}
updateRoute (route: Route) { const prev = this.current this.current = route this.cb && this.cb(route) this.router.afterHooks.forEach(hook => { hook && hook(route, prev) }) }
history.listen(route => { this.apps.forEach((app) => { app._route = route }) })