Vue正式篇(二)全家桶vue-router

vue-router
Vue Router是Vue.js官方的路由管理器。它是Vue.js的核心深度集成,让构建单页面应用变得易如反掌。
安装:vue add router
核心步骤:

  • 步骤一:使用vue-router插件,router.js
    import Router from 'vue-router'
    Vue.use(Router)
    
  • 步骤二:创建Router实例,router.js
    export default new Router({...})
    
  • 步骤三:在根组件上添加该实例,main.js
    import router from './router'
    new Vue({
    	router,
    }).$mount('#app')
    
  • 步骤四:添加路由视图,APP.vue
    <router-view></router-view>
    
  • 导航
    <router-link to="/">Home</router-link>
    <router-link to="/about">About</router-link>
    

vue-router源码实现
需求分析:

  • 作为一个插件存在:实现VueRouter类和install方法
  • 实现两个全局组件:router-view用于显示匹配组件内容,router-link用于跳转
  • 监控url变化:监听hashchange或popstate事件
  • 响应最新url:创建一个响应式的属性current,当它改变时获取对应组件并显示

实现一个插件:创建VueRouter类和install方法
创建kue-router.js

let Vue;		// 引用构造函数,VueRouter中要使用

// 保存选项
class VueRouter{
	constructor(options) {
		this.$options = options
	}
}

// 插件:实现install方法,注册$router
VueRouter.install = function(_Vue) {
	// 引用构造函数,VueRouter中要使用
	Vue = _Vue
	Vue.mixin({
		beforeCreate() {
			// 只有根组件拥有router选项
			if(this.$options.router) {
				// vm.$router
				Vue.prototype.$router = this.$options.router
			}
		}
	})
}
export default VueRouter

注:为什么要用混入方式写?主要原因是use代码在前,Router实例创建在后,而install逻辑又需要用到该实例

创建router-view和router-link
创建krouter-link.js

export default {
	props: {
		to: String,
		required: true
	},
	render(h) {
		// return <a href={'#' + this.to}>{this.$slots.default}</a>
		return h('a', {
			attrs: {
				href: '#' + this.to
			}
		}, [
			this.$slots.default
		])
	}
}

创建router-view.js

export default{
	render(h) {
		// 暂时先不渲染任何内容
		return h(null)
	}
}

监控url变化
定义响应式的current属性,监听hashchange事件

class VueRouter {
	constructor(options) {
		// current应该是响应式的
		Vue.util.defineReactive(this, 'current', '/')

		// 定义响应式的属性current
		const initial = window.location.hash.slice(1) || '/'
		Vue.util.defineReactive(this, 'current', initial)

		// 监听hashchange事件
		window.addEventListener('hashchange', this.onHashChange.bind(this))
		window.addEventListener('load', this.onHashChange.bind(this))
	}
	onHashChange() {
		this.current = window.location.hash.slice(1)
	}
}

动态获取对应组件,krouter-view.js

export dfault {
	render(h) {
		// 动态获取对应组件
		let component = null;
		this.$router.$options.routes.forEach(route => {
			if(route.path === this.$router.current) {
				component = route.component
			}
 		})
 		return h(component)
	}
}

提前处理路由表
提前处理路由表避免每次都循环

class VueRouter {
	constructor(options) {
		// 缓存path和route映射关系
		this.routeMap = {}
		this.$options.routes.forEach(route => {
			this.routeMap[route.path] = route
		})
	}
}

使用krouter-view.js

export default {
	render(h) {
		const {routeMap, current} = this.$router
		const component = routeMap[current].component
		return h(component)
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值