用户点击链接元素:
户点击链接交互,即点击了 <router-link>
props: {tag: {type: String,default: 'a'}, // 绑定的事件event: {type: eventTypes,default: 'click'}},render (h: Function) {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} return h(this.tag, data, this.$slots.default) }
该组件主要是通过render函数,默认创建一个a标签,同时为标签绑定click事件
在绑定事件的函数中,值得注意guardEvent执行操作:
function guardEvent (e) { // 忽略带有功能键的点击if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return
// 调用preventDefault时不重定向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}// 判断是否存在`e.preventDefault`,在 weex 中没有这个方法if (e.preventDefault) {e.preventDefault()}return true
}
可以看到,这里主要对是否跳转进行了一些判断。再看看点击事件的处理函数:
const handler = e => {if (guardEvent(e)) {if (this.replace) {router.replace(location)} else {router.push(location)}}
}
可以看到其实他们只是代理而已,真正做事情的还是 history 来做:
浏览器本身的跳转动作
对于这种情况,先来看 hash的方式,当发生变得时候会判断当前浏览器环境是否支持 supportsPushState 来选择监听 popstate还是hashchange
window.addEventListener(supportsPushState ? 'popstate' : 'hashchange', () => {const current = this.currentif (!ensureSlash()) {return}this.transitionTo(getHash(), route => {if (supportsScroll) {handleScroll(this.router, route, current, true)}if (!supportsPushState) {replaceHash(route.fullPath)}})
})
对应的history其实也是差不多。只不顾既然是history模式了,默认也就只用监听popstate
window.addEventListener('popstate', e => {const current = this.currentconst location = getLocation(this.base)if (this.current === START && location === initLocation) {return}this.transitionTo(location, route => {if (supportsScroll) {handleScroll(router, route, current, true)}})
})