1.Vue Router是什么?
Vue Router 是 Vue.js 的官方路由。它与 Vue.js 核心深度集成,让用 Vue.js 构建单页应用变得轻而易举。功能包括:
- 嵌套路由映射
- 动态路由选择
- 模块化、基于组件的路由配置
- 路由参数、查询、通配符
- 展示由 Vue.js 的过渡系统提供的过渡效果
- 细致的导航控制
- 自动激活 CSS 类的链接
- HTML5 history 模式或 hash 模式
- 可定制的滚动行为
- URL 的正确编码
2.Vue Router的使用方式
安装: vue add router
核心步骤:
- 步骤一:使用vue-router插件
import Router from 'vue-router'
Vue.use(Router)
- 步骤二:创建Router实例
export default new Router({
routes: [{...}]
})
- 步骤三:在根组件上添加该实例
import router from './router'
new Vue({
router,
}).$mount('#app')
- 步骤四:添加路由视图
<router-view/>
- 导航
<router-link to="/">helloWorld</router-link>
<router-link to="/source">源码</router-link>
3. Vue Router源码实现
3.1 ⭐️ 需求分析
根据上面的使用方式
Vue.use(Router) : 作为一个插件存在
export default new Router({…}) : vueRouter是一个类
vueRouter主要做的事情就是:监听路由的变化,当路由变化时,响应式的替换router-view中的视图内容。
所以我们自己写的这个简版的vue-router就需要满足以下需求:
- 作为一个插件存在: 实现VueRouter类和install方法
- 实现两个全局组件: router-view用于显示匹配组件内容,router-link用于跳转
- 监控url变化: 监听hashchange或popstate事件
- 响应最新url: 创建一个响应式的属性current,当它改变时获取对应组件并显示
3.2 🌷 准备知识:
- 插件
- 混入
- 自定义组件
对以上不了的同学可以先看我之前的两篇文章:
vue进阶:混入mixin
vue进阶:使用插件实现弹窗类组件
3.3 🍀 代码实现
按照需求一,先写个类出来,并且作为一个插件
class VueRouter {
constructor (props) {
this.$options = props
}
}
VueRouter.install = function (Vue) {
_Vue = Vue
}
export default VueRouter
上面的类VueRouter的构造函数中的props,就是new Router({routes: [{…}]})中的{routes: [{…}]}
先来看install方法:
VueRouter.install = function (Vue) {
_Vue = Vue
// 1. 挂载$router
Vue.mixin({
beforeCreate () {
// 只有根组件拥有router选项 所以这里判断下
if (this.$options.router) {
Vue.prototype.$router = this.$options.router
}
}
})
}
vue 调用插件的时候,会给插件传递一个Vue实例,把这个保存下,便于在类实现中使用。挂载$router需要用到vue中的混入, 注意看上面的使用VueRouter的步骤代码, Vue.use(Router)在前,此刻还没有VueRouter实例,而install逻辑又需要用到该实例,所以这里使用混入,待beforeCreate时再去挂载 $router 实例。挂载该实例是为了在组件中能够拿到。
接下来实现下监听路由变化和存储路由表,便于在自定义组件router-view中渲染当前路径对应的component。
let _Vue
class VueRouter {
constructor (props) {
this.$options = props
const initial = window.location.hash.slice(1) || '/'
// 使current变成响应式
_Vue.util.defineReactive(this, 'current', initial)
// 处理path与route映射表
this.routeMap = {}
if (this.$options.routes) {
this.$options.routes.forEach(route => {
this.routeMap[route.path] = route
})
}
// 监听hash路由变化
window.addEventListener('hashchange', this.onHashChange)
}
onHashChange = () => {
// 只取 # 号后部分
this.current = window.location.hash.slice(1)
}
}
响应式这里使用了vue提供的Vue.util.defineReactive()方法。
然后就是实现注册组件router-view router-link了:
let _Vue
class VueRouter {
constructor (props) {
this.$options = props
const initial = window.location.hash.slice(1) || '/'
_Vue.util.defineReactive(this, 'current', initial)
this.routeMap = {}
if (this.$options.routes) {
this.$options.routes.forEach(route => {
this.routeMap[route.path] = route
})
}
// 监听hash路由变化
window.addEventListener('hashchange', this.onHashChange)
}
onHashChange = () => {
this.current = window.location.hash.slice(1)
}
}
VueRouter.install = function (Vue) {
_Vue = Vue
// 1. 挂载$router
Vue.mixin({
beforeCreate () {
if (this.$options.router) {
Vue.prototype.$router = this.$options.router
}
}
})
// 2.注册组件,router-view router-link
Vue.component('router-link', {
render (h) {
return h('a', {
attrs: {
href: '/#' + this.to
}
}, this.$slots.default)
},
props: {
to: {
type: String,
required: true
}
}
})
Vue.component('router-view', {
render (h) {
const { routeMap, current } = this.$router
return h(routeMap[current] ? routeMap[current].component : null)
}
})
}
export default VueRouter
知识点:
this.$slots.default: 获取组件的子节点
关键点:搞懂各个作用域内this的指向!
至此,一个基础的简版vue-router就实现了。这也是vueRouter官方实现的核心思路,这里看懂了,再去看源码会更简单很多。

本文详细解析Vue Router的基本概念、安装与使用,重点在于简版Vue Router的源码实现,涵盖需求分析、必备知识及代码实现。通过实现VueRouter类,监听url变化,响应式替换视图内容,注册全局组件router-view和router-link,帮助读者深入理解Vue Router的工作原理。

287

被折叠的 条评论
为什么被折叠?



