赞
踩
这是对vue-router 3 版本的源码分析。
本次分析会按以下方法进行:
本章讲解router中 router-link 组件是如何实现导航的。
另外我的vuex3源码分析也发布完了,欢迎大家学习:
vuex3 最全面最透彻的源码分析
还有vue-router的源码分析:
vue-router 源码分析——1. 路由匹配
vue-router 源码分析——2. router-link 组件是如何实现导航的
vue-router 源码分析——3. 动态路由匹配
vue-router 源码分析——4.嵌套路由
<script src="https://unpkg.com/vue@2/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router@3/dist/vue-router.js"></script>
<div id="app">
<h1>Hello App!</h1>
<p>
<!-- 使用 router-link 组件来导航. -->
<!-- 通过传入 `to` 属性指定链接. -->
<!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
<router-link to="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
</p>
</div>
// ./install.js
import Link from './components/link'
export function install(Vue) {
Vue.component('RouterLink', Link)
}
const { location, route, href } = router.resolve(
this.to,
current,
this.append
)
...
const classes = {}
const data: any = { class: classes }
...
return h(this.tag, data, this.$slots.default)
}
}
// ./router.js export default class VueRouter { ... resolve ( to: RawLocation, current?: Route, append?: boolean ) { ... const location = normalizeLocation(to, current, append, this) const route = this.match(location, current) const fullPath = route.redirectedFrom || route.fullPath const base = this.history.base const href = createHref(base, fullPath, this.mode) // this.mode 看做 'hash' 即可 return { location, route, href ... } } }
// ./util/location.js export function normalizeLocation( raw: RawLocation, current: ?Route, append: ?boolean, router: ?VueRouter ): Location { let next: Location = typeof raw === 'string' ? { path: raw } : raw if (next._normalized) { return next } ... // parsePath 的实际内容为 {'path': '/foo', 'query': '', 'hash': ''} const parsedPath = parsePath(next.path || '') // basePath 为当前的路由的路径 const basePath = (current && current.path) || '/' // resolvePath函数对'/foo'也没有额外影响,可以理解直接返回了'/foo'赋值给path const path = parsedPath.path ? resolvePath(parsedPath.path, basePath, append || next.append) : basePath ... return { _normalized: true, path, ... } }
// ./router.js export default class VueRouter { ... match (raw: RawLocation, current?: Route, redirectedFrom?: Location): Route { return this.matcher.match(raw, current, redirectedFrom) } } // ./create-matcher.js export function createMatcher(...) { ... function match { raw: RawLocation, currentRoute?: Route, redirectedFrom?: Location }: Route { // 由于传入的raw是已经标准化过的,所以这里的location和raw没有任何区别 const location = normalizedLocation(raw, currentRoute, false, router) const { name } = location if (name) { ... } else if (location.path) { location.params = {} for (let i = 0; i < pathList.length; i++) { const path = pathList[i] const record = pathMap[path] if (matchRoute(record.regex, location.path, location.param)) { return _createRoute(record, location, redirectedFrom) } } } } function matchRoute( regex: RouteRegExp, path: string, params: Object ): boolean { const m = path.match(regex) if (!m) { return false } else if (!params) { return true } ... return true } function _createRoute( record: ?RouteRecord, location: Location, redirectedFrom?: Location ): Route { ... return createRoute(record, location. redirectedFrom, router) } } // ./util/route.js export function createRoute( record: ?RouteRecord, location: Location, redirectedFrom?: ?Location, router?: VueRouter ): Route { const route: Route = { path: location.path || '/', matched: record ? formatMatch(record) :[], // 这里可以先简单理解为 [record] ... } return Object.freeze(route) }
// ./router.js
function createHref(base: string, fullPath: string, mode) {
var path = mode === 'hash' ? '#' + fullPath : fullPath
return base ? cleanPath(base + '/' + path) : path
}
// ./router.js export default class VueRouter { ... resolve(to, current, append) { const location = normalizeLocation(to, current, append, this) const route = this.match(location, current) const fullPath = route.redirectedFrom || route.fullPath const base = this.history.base const href = createHref(base, fullPath, this.mode) return { location, route, href, ... } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。