###################
npm install vue-router
<router-link to="/user" tag="button" active-class="active" exact>Go to User Page</router-link>
这个例子中,当用户点击按钮时,会跳转到 /user
路由,并且按钮会添加 active
类名。另外,由于开启了精确匹配模式,只有当路径与目标路由完全匹配时才会添加 active
类名。
Vue.use()方法的源代码如下:
function install(Vue) {
// 避免重复安装插件
if (install.installed && _Vue === Vue) return
install.installed = true
_Vue = Vue
// 执行插件的安装方法
const isDef = val => val !== undefined
const registerInstance = (vm, callVal) => {
let i = vm.$options._parentVnode
if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
i(vm, callVal)
}
}
_Vue.mixin({
beforeCreate() {
// 如果有router选项,则把router挂在到vue实例上
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)
},
})
// 注册router-link和router-view全局组件
_Vue.component('RouterView', View)
_Vue.component('RouterLink', Link)
// 在Vue原型上定义$router和$route属性
Object.defineProperty(Vue.prototype, '$router', {
get() { return this._routerRoot._router }
})
Object.defineProperty(Vue.prototype, '$route', {
get() { return this._routerRoot._route }
})
// 注册钩子函数,用于处理VueRouter的生命周期
Vue.mixin({
beforeRouteEnter(to, from, next) {
next(vm => {
if (!vm._isMounted) {
// 如果Vue组件没有挂载,则在挂载时再执行beforeRouteEnter函数
vm.$nextTick(() => {
next(vm)
})
}
})
},
beforeRouteUpdate(to, from, next) {
const { matched } = this.$route
const prevMatched = from.matched
let diffed = false
const activated = matched.filter((c, i) => {
return diffed || (diffed = (prevMatched[i] !== c))
})
if (!activated.length) {
this.$nextTick(() => {
next()
})
} else {
const queue = activated.map(c => {
return new Promise((resolve, reject) => {
if (c.beforeRouteEnter) {
c.beforeRouteEnter(to, from, () => {
resolve()
})
} else {
resolve()
}
})
})
Promise.all(queue).then(() => {
next()
}).catch(() => {
next(false)
})
}
},
beforeRouteLeave(to, from, next) {
const matched = this.$route.matched
const component = matched[matched.length - 1]
if (!component || !component.beforeRouteLeave) {
next()
} else {
component.beforeRouteLeave(to, from, () => {
next()
})
}
}
})
}
export default {
install,
}
##########################