VueRouter.install = install
VueRouter.version = '__VERSION__'
VueRouter.isNavigationFailure = isNavigationFailure
VueRouter.NavigationFailureType = NavigationFailureType
VueRouter.START_LOCATION = START
install
export let _Vue
export function install(Vue){
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.registerRouterInstance)){
i(vm,callVal)
}
}
Vue.mixin({
beforeCreate(){
if(isDef(this.$options.router)){
this._routerRoot = this
this._router = this.$options.router
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)
}
})
Object.defineProperty(Vue.prototype,'$router',{
get(){ return this._routerRoot._router}
})
Object.defineProperty(Vue.prototype,'$route',{
get() { return this._routerRoot._route}
})
Vue.component('RouterView',view)
Vue.component('RouterLink',link)
const strats = Vue.config.optionMergeStrategies
strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created
}
RouterView
export default {
name: 'RouterView',
functional:true,
props:{
name:{type:String,default:'default'},
},
render(_,{props,children,parent,data}){
data.routerView = true
const h = parent.$createElement
const name = props.name
const router = parent.$route
const cache = parent._routerViewCache || (parent._routerViewCache = {})
let depth = 0
let inactive = false
while(parent && parent._routerRoot !== parent){
const vnodeData = parent.$vnode ? parent.$vnode.data : {}
if(vnodeData.routerView){
depth ++
}
if(vnodeData.keepAlive && parent._directInactive && parent._inactive){
inactive = true
}
parent = parent.$parent
}
data.routerViewDepth = depth
if(inactive){
const cacheData = cache[name]
const cacheComponent = cacheData && cacheData.component
if(cacheComponent){
if(cacheData.configProps){
fillPropsinData(cacheComponent,data,cacheData.route,cacheData.configProps)
}
return h(cacheComponent,data,children)
}else{
return h()
}
}
const matched = route.matched[depth]
const component = matched && matched.components[name]
if(!matched || !component){
cache[name] = null
return h()
}
cache[name] = { component }
data.registerRouteInstance = (vm,val) => {
const current = matched.instances[name]
if((val && current !== vm) || (!val && current === vm)){
matched.instances[name] = vm
}
}
;(data.hook || (data.hook = {})).prepatch = (_,vnode) => {
matched.instances[name] = vnode.componentInstance
}
data.hook.init = (vnode) => {
if(vnode.data.keepAlive && vnode.componentInstance && vnode.componentInstance !== matched.instances[name]){
matched.instances[name] = vnode.componentInstance
}
handleRouterEntered(route)
}
const configProps = matched.props && matched.props[name]
if(configPorps){
extend(cache[name],{
route,
configProps
})
fillPropsinData(component,data,route,configProps)
}
return h(component,data,children)
}
}
RouterLink
let warnedCustomSlot
let warnedTagProp
let warnedEventProp
export default{
name:'RouterLink',
props:{
to:{ type: toTypes, required: true},
tag: { type:String, default: 'a'},
custom:Boolean,
exact:Boolean,
exactPath:Boolean,
append:Boolean,
replace:Boolean,
activeClass:String,
exactActiveClass:String,
ariaCurrentValue:{ type: String, default: 'page'},
event: {type: eventTypes, default:'click'}
},
render(h){
const router = this.$router
const current = this.$route
const { location, route, href } = router.resolve(this.to,current,this.append)
const classes = {}
const globalActiveClass = router.options.linkActiveClass
const globalExactActiveClass = router.options.linkExactActiveClass
const activeClassFallBack = globalActiveClass == null ? 'router-link-active' : globalActiveClass
const exactActiveClassFallBack = globalExactActiveClass == null ? 'router-link-exact-active' : globalExactActiveClass
const activeClass = this.activeClass == null ? activeClassFallBack : this.activeClass
const exactActiveClass = this.exactActiveClass == null ? exactActiveClassFallBack : this.exactActiveClass
const compareTarget = route.redirectedFrom ? createRoute(null,normalizeLocation(route.redirectedFrom),null,router) : route
classes[exactActiveClass] = isSameRoute(current,compareTarget,this.exactPath)
classes[activeClass] = this.exact || this.exactPath ? classes[exactiveClass] : isIncludedRoute(current,compareTarget)
const ariaCurrentValue = classes[exactActiveClass] ? this.ariaCurrentValue : null
const handler = e => {
if(guardEvent(e)){
if(this.replace){
router.replace(location,noop)
}else{
router.push(location,noop)
}
}
}
const on = {click:guardEvent}
if(Array.isArray(this.event)){
this.event.forEach(e => {
on[e] = handler
})
}else{
on[this.event] = handler
}
const data = {class:classes}
const scopedSlot = !this.$scopedSlots.$hasNormal && this.$scopedSlots.default && this.$scopedSlots.default({href,route,navigate:handler,isActive:classes[activeClass],isExactActive:classes[exactActiveClass]})
if(scopedSlot){
...
if(scopedSlot.length === 1){
return scopedSlot[0]
}else if(scopedSlot.length > 1 || !scopedSlot.length){
...
return scopedSlot.length === 0 ? h() : h('span',{},scopedSlot)
}
}
if(process.env.NODE_ENV !== 'production'){
...
...
}
if(this.tag === 'a'){
data.on = on
data.attrs = { href, 'aria-current':ariaCurrentValue }
}else{
const a = findAnchor(this.$slots.default)
if(a){
a.isStatic = false
const aData = (a.data = extend({},a.data))
aData.on = aData.on || {}
for(const event in aData.on){
const handler = aData.on[event]
if(event in on){
aData.on[event] = Array.isArray(handler) ? handler : [handler]
}
}
for(const event in on){
if(event in aData.on){
aData.on[event].push(on[event])
}else{
aData.on[event] = [on[event]]
}
}
const aAttrs = (a.data.attrs = extend({},a.data.attrs))
aAttrs.href = href
aAttrs['aria-current'] = arriaCurrentValue
}else{
data.on = on
}
}
return h(this.tag,data,this.$slot.default)
}
}
isNavigationFailure
export function isNavigationFailure(err,errorType){
return isError(err) && err._isRouter && (errorType == null || err.type === errorType)
}
NavigationFailureType
export const NavigationFailureType = {
redirected:2,
aborted:4,
canceled:8,
duplicated:16
}