携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第16天,点击查看活动详情
前言
接触vue,总有一个绕不开的一个话题,就是它vue-router。要知道,现在的路由都是前端来做,而vue这种SPA项目的路由工作就是由vue-router来完成的。套用官网的一句话:它是和vue.js的核心深度集成,让单页面应用变得易如反掌,经过工作一年的实践,确实如此。
认识vue-router
在vue项目中,由于是单页面应用,就是只有一个html文件,内容都是以组件的粒度去展示的。而页面中肯定不只一个地址,那么就需要将地址和组件联系起来,vue-router就是干这件事的。我们在vue-router中将路径和组件绑定在一起,然后告诉它在哪里渲染组件。当然也额外带了一些功能,例如:带参。
实现
vue-router接受一个object作为参数,里面包含了路由的模式(mode)和路由数组。所以我们需要在路由构造类里面有一个数组去保存路由数组。其次我们还得用一个变量去保存当前的地址。随后就是模式了,官网默认是hash模式。总结一下:
- routes:用于保持传入到构造类中的路由数组
- current:用于保存当前的地址
- mode:指定当前的路由模式
第一步:我们先创建一个myRouter类和上述的基本变量:
class myRouter{
constructor(options){
this.current = null;
this.routes = options.routes;
this.mode = options.mode || "hash";
}
}
第二步:刚开始访问的网址的hash是#/,所以我们得监听load事件,并将当前的hash值赋给current,同时将components渲染到页面上:
class myRouter{
constructor(options){
this.current = null;
this.routes = options.routes;
this.mode = options.mode || "hash";
this.init()
}
init(){
if(this.mode === 'hash'){
window.addEventListener('load',this.setCurrent);
window.addEventListener("hashchange",this.setCurrent);
}
}
setCurrent(){
this.current = location.hash.slice(1)
console.log(this.current)//1
}
}
myRouter.install = function(vue){
}
export default myRouter
现在我们做到了在页面初始化的时候和hash改变时将地址hash给current,但是并没有渲染组件呢?接下来就做一个router-view,而它也是一个组件,所以直接在全局注册一个组件:
- 拿到current
- 从routes中依据current找到component
- 使用render函数渲染组件
let vue=null;
class myRouter {
constructor(options) {
this.current = null;
vue.util.defineReactive(this,"current",'/')
this.routes = options.routes;
this.init();
this.mode = options.mode || "hash";
}
init() {
if (this.mode === 'hash') {
window.addEventListener('load', this.setCurrent);
window.addEventListener("hashchange", this.setCurrent);
}
}
setCurrent() {
this.current = location.hash.slice(1);
console.log(this.current)
}
}
myRouter.install = function (_vue) {
vue = _vue;
vue.mixin({
beforeCreate() {
console.log(this)
// 如果是跟组件的话将this和router取出来
if (this.$options?.router) {
this._root = this;
this._router = this.$options.router
console.log(this._router)
} else {
// 不是的话就去找
this._root = this.$parent?._root;
}
Object.defineProperty(this, "$router", {
get() {
return this._root._router
}
})
}
})
vue.component("router-link", {
render() {
return
}
})
// router-view
vue.component("router-view", {
render(h) {
console.log(this.$router.routes)
const current = this.$router.current;
console.log(current)
const component = this.$router.routes.find(item => item.path === current);
console.log(component)
return h(component.component)
}
})
}
export default myRouter
现在页面能够渲染组件了,但是跳转还不行,router-link的本质是a标签,所以的注册的一个全局组件render``a标签。
.......
vue.component("router-link", {
props: ['to'],
render(h) {
return h("a", { attrs: { href: `#${this.to}` } }, this.$slots.default)
}
})
.......

end
到此一个基本的路由就搞定了,但是还是缺少的好多,比如history模式,带上参数之类的。这些下次再搞定吧,休息休息。