追踪replace和push的调用,这两个方法的触发通过我们定义的router-link组件
render (h: Function) {
const router = this.$router //路由对象
const current = this.$route //当前路由
//解析 to的路径对应路由项
const { location, route, href } = router.resolve(this.to, current, this.append)
//设置一些默认元素class
const classes = {}
const globalActiveClass = router.options.linkActiveClass
const globalExactActiveClass = router.options.linkExactActiveClass
// Support global empty active class
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 = location.path
? createRoute(null, location, null, router)
: route
// 如果严格模式的话 就判断是否是相同路由(path query params hash)
// 否则就走包含逻辑(path包含,query包含 hash为空或者相同)
classes[exactActiveClass] = isSameRoute(current, compareTarget)
classes[activeClass] = this.exact
? classes[exactActiveClass]
: isIncludedRoute(current, compareTarget)
//事件处理函数
const handler = e => {
if (guardEvent(e)) {
if (this.replace) {//路由replace触发改变router-view
router.replace(location)
} else {//路由push触发改变router-view
router.push(location)
}
}
}
//事件对象
const on = { click: guardEvent }
if (Array.isArray(this.event)) {
this.event.forEach(e => { on[e] = handler })
} else {
on[this.event] = handler
}
//添加元素的类
const data: any = {
class: classes
}
if (this.tag === 'a') {
data.on = on
data.attrs = { href }
} else {
// find the first <a> child and apply listener and href
const a = findAnchor(this.$slots.default)
if (a) {
// in case the <a> is a static node
a.isStatic = false
const extend = _Vue.util.extend
const aData = a.data = extend({}, a.data)
aData.on = on
const aAttrs = a.data.attrs = extend({}, a.data.attrs)
aAttrs.href = href
} else {
// doesn't have <a> child, apply listener to self
data.on = on
}
}
return h(this.tag, data, this.$slots.default)
}
}
function guardEvent (e) {
// 忽略带有功能键的点击
if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return
// 已阻止的返回
if (e.defaultPrevented) return
// 右击
if (e.button !== undefined && e.button !== 0) return
// `target="_blank"` 忽略
if (e.currentTarget && e.currentTarget.getAttribute) {
const target = e.currentTarget.getAttribute('target')
if (/\b_blank\b/i.test(target)) return
}
// 阻止默认行为 防止跳转
if (e.preventDefault) {
e.preventDefault()
}
return true
}
//找到第一个A标签
function findAnchor (children) {
if (children) {
let child
for (let i = 0; i < children.length; i++) {
child = children[i]
if (child.tag === 'a') {
return child
}
if (child.children && (child = findAnchor(child.children))) {
return child
}
}
}
}
复制代码
可以看到router-link绑定了click 方法调用replace和push 达到更新路由目的。