手撕Vue-Router-实现router-link
前言
在上一篇 [手撕Vue-Router-添加全局$router属性]
中,实现了将每一个 Vue 实例上挂载一个 $router
属性,这个属性就是我们在上一篇文章中创建的 VueRouter 实例。
开始
本章节,我们将实现一个 router-link
组件,这个组件可以实现点击跳转到指定的路由。
实现思路
我们需要实现一个 router-link
组件,这个组件可以实现点击跳转到指定的路由。
实现 router-link 组件,我们需要注意以下几点:
- 只要外界使用了Vue-Router, 那么我们就必须提供两个自定义的组件给外界使用,一个是
router-link
组件,一个是router-view
组件。 - 只要外界通过Vue.use注册了Vue-Router, 就代表外界使用了Vue-Router
- 只要外界通过Vue.use注册了Vue-Router, 就会调用插件的install方法
- 所以我们只需要在install方法中注册两个全局组件给外界使用即可
代码实现
- 只要外界使用了Vue-Router, 那么我们就必须提供两个自定义的组件给外界使用,一个是
router-link
组件,一个是router-view
组件。首先本章节我们只实现router-link
组件。 - 只要外界通过Vue.use注册了Vue-Router, 就代表外界使用了Vue-Router
- 只要外界通过Vue.use注册了Vue-Router, 就会调用插件的install方法
- 所以我们只需要在install方法中注册两个全局组件给外界使用即可
代码如下:
NueRouter.install = (Vue, options) => {
...
Vue.component('router-link', {
});
}
好了到此为止,就完成了添加 router-link 组件,只是简简单单的添加了一个组件,还没有实现跳转的功能。
实现跳转功能
通过观察官方的 router-link
组件,我们可以发现,这个组件是一个 <a>
标签,所以我们可以通过 <a>
标签的 href
属性来实现跳转。
这么一来,在根据 Vue 官方文档中介绍的组件注册方式,我们可以在 component 中使用 render 函数来实现渲染 a 标签。
a 标签渲染完毕了但是跳转的地址还没有,还需要在 component 中添加一个 props 属性,这个属性就是我们要跳转的地址。
总结:通过 render 函数渲染 a 标签,通过 props 属性传递跳转地址。
代码如下:
Vue.component('router-link', {
props: {
to: {
type: String,
}
},
render() {
return <a href={this.to}></a>
}
});
写完发现,a 标签渲染了,但是没有内容,我们需要在 a 标签中添加内容,这个内容就是我们在使用 router-link 组件时传入的内容。
我们可以通过 this.$slots.default
来获取到我们在使用 router-link 组件时传入的内容。
代码如下:
return <a href={this.to}>{this.$slots.default}</a>
测试自己写的 router-link 组件,发现可以改变了,发现还有一个问题,就是路由的 mode 为 hash 时,生成的 a 标签的 href 属性是 /#/xxx
,如果 mode 为 history 时,生成的 a 标签的 href 属性是 /xxx
, 这个问题我们还需要解决。
那么怎么获取到路由的 mode 呢?我们可以通过 this.$router.mode
来获取到路由的 mode。
这里有一个注意点:
render 方法中的 this 并不是当前实例对象, 而是一个代理对象, 如果我们想拿到当前实例对象,那么可以通过
this._self
获取
知道了这些内容之后,我们就可以通过 this._self.$router.mode
来获取到路由的 mode 了。根据路由的 mode 来判断生成的 a 标签的 href 属性。
代码如下:
render() {
let path = this.to;
if (this._self.$router.mode === 'hash') {
path = '#' + path;
}
return <a href={path}>{this.$slots.default}</a>
}
测试一下,发现可以了。好了,到此为止,我们就完成了 router-link
组件的实现。
最后
大家好我是 BNTang, 一个热爱分享的技术的开发者,如果大家觉得我的文章对你有帮助的话,可以关注我的公众号 JavaBoyL
,我会在公众号中分享一些IT技术和一些个人的见解,谢谢大家的支持。