实现一个vue-router

实现一个vue-router

我们都知道Vue提供了两种路由方式(hash/history),这两种方法都是利用了浏览器自身的特性。

1.mode: hash ->  www.router.com/#/myrouter  hash的值就是 #/myrouter,
特点是虽然出现在url中,但是不会出现在http请求中,对后端没影响,其改变不会引起页面重新加载。
2.mode:history -> 利用了H5中 History Interface 新增的 pushState 和 replaceState方法来修改历史记录栈。

今天以hash为例,实现一个简版vue-router

首先明确一下需求

需求一:实现VueRouter这个类,里面要做的事儿有3点
1.处理路由选项
2.监控url变化(hashchange)
3.响应url的变化
需求二:实现install方法
1.$router的挂载
2.两个全局组件(router-link,router-view)
补充一下:
⑴我们使用router的时候,Vue.use(Router),从use方法底层可以知道,先把你传入的这个Router做判断,是否有install函数,有就执行,并传入Vue对象作为第一个参数
⑵在install方法执行的时候,我们可以发现,这个时刻是非常早的,就是第一点中的Vue.use 时发生的,我们可以利用Vue.mixin 混入的方式推迟执行(beforeCreate的时机)从而做一些内容

开始启动!!!

1.先用vue-cli初始化带有vue-router一个项目,结构如下

在这里插入图片描述

2.然后我们在router文件夹下面新建一个myRouter.js,在router/index.js里面修改一下引用,换成我们自己的路径。
在这里插入图片描述
3.进入到我们的myRouter.js中,架子

class myRouter{
	constructor(options) {
			// 保存一下用户传入的路由表
        	this.$options = options
        }
}
myRouter.install = function() {}
export default myRouter

4.先实现install方法,利用了Vue.mixin混入的方式来改变执行时机,确保有router并挂载上,保存一个变量Vue,一会有用!

myRouter.install = function(Vue) {
_Vue = Vue // 先保存,一会有用
    // 挂载$router  
    Vue.mixin({
        beforeCreate() {
            // 此处this指的是组件实例 let vm = new Vue()  指向vm
            // 利用了全局混入的方式,,在beforeCreate中来推迟执行时机
            // 需要判断来保证传入了路由表router,因为并不是每一个组件都有router
            if (this.$options.router) {
                // $route 同理
                Vue.prototype.$router = this.$options.router
            }
        }
    })

    // 2.定义两个全局组件router-link,router-view
    Vue.component('router-link', {
        props: {
            to: {
                type: String,
                require: true
            },
        },
        render(h) {
            // 看看用法 <router-link to="/list">
            // 看看用法  <a href="#/list">xxx</a>
            // 看看用法  <a href={'#'+this.to}>{this.$slots.default}</a>
            return h('a', {
                attrs: {
                    href: '#' + this.to
                }
            }, this.$slots.default)  // 默认内容,写在标签里的
        }
    })
    Vue.component('router-view', {
        render(h) {
        	// 先什么都不渲染 ,在第6点等你!
            return h(null)
        }
    })
}

5.现在回到myRouter类里面,任务就是拿到hash,用户传入的路由表,对应上

class myRouter {
    constructor(options) {
        // 保存一下用户传入的路由表
        this.$options = options

        // routes: [{
        //     path: '/home',
        //     name: 'home',
        //     component: Home
        //    },
        //    {
        //     path: '/list',
        //     name: 'list',
        //     component: List
        //    }
        // ]
        // 建个对象,参照用户传入路由配置来拿到映射关系
        // routeList = { /home:  {path: '/home',...}} 有了这个对象后 通过hash来对应组件,以供渲染
        this.routeList = {}
        this.$options.routes.forEach(
                route => {
                    this.routeList[route.path] = route
                })
            // console.log(this.routeList)
            // 再来定义一个响应式的currentPath属性,截取掉hash的# 就行和routeList呼应上了,顺便给个默认值
        const initPath = window.location.hash.slice(1) || '/'
            // 当前hash 举例为 #/list  取到/list 做成响应式,否则只发生一次,做不到响应变化从而渲染对应组件
            // 这个时候保存的_Vue 就有用了,通过底层提供的方法来设置,也可以外部引入Vue,太浪费了~
            // 另外说一下在下面install保存的这个Vue变量,因为install执行的时间是非常早的,先Vue.use 再实例化的,此时就存在了  对吧!
        _Vue.util.defineReactive(this, 'currentPath', initPath)


        // 监控url变化 bind一下,预防一下 下面的上下文 调用问题
        window.addEventListener('hashchange', this.onHashChange.bind(this))
    }

    onHashChange() {
        // 监听这个方法来得到currentPath
        // 只要#后面部分,呼应上!
        this.currentPath = window.location.hash.slice(1)
    }
}

6.看完注释后,我们记得之前全局组件router-view里面渲染的还是空呢,现在对号入组,监听的hash变了,currentPath变了就响应上了,然后渲染的组件就更新了~

Vue.component('router-view', {
        render(h) {
            // 找到当前url对应的组件,解构一下方便看
            const { routeList, currentPath } = this.$router
            const component = routeList[currentPath] ? routeList[currentPath].component : null
                // 渲染对应的组件
            return h(component)
        }
    })

大功告成,跳转,渲染都是OK的!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值