vue-router
vue-router 是vue.js的官方路由管理器.它和vue.js核心深度集成.让构建单页面应用易如反掌
使用步骤
(1) 安装 vue add router
(2) 使用vue-router插件
import Router from 'vue-router'
Vue.use(Router)
(3) 创建Router实例 router.js
export default new Router({...})
(4) 在根组件上添加该实例 main.js
import Router from './router'
new Vue({
router,
}).$mount("#app");
(5) 添加路由视图 App.vue
<router-view></router-view>
(6) 路由导航
<router-link to="/">Home</router-link>
this.$router.push('/')
vue-router 源码简单实现
单页面程序中,url发生变化的时候,不刷新页面,显示对应视图
需求分析
(1) 页面不刷新
hash模式 #/about
(2) 页面视图发生变化
router-view
相应式数据: url地址发生变化,找到对应的组件 动态重新执行 render
任务实现一个插件
(1) 实现一个vueRouter类
处理路由选项
监控url变化, hashchange
响应这个变化
(2) 实现install方法
$router注册
两个全局组件 router-link router-view
实现一个插件:创建VueRouter类和install方法
创建kvue-router.js
let Vue; // 引用构造函数, vueRouter中要使用
class VueRouter {
constructor(options) {
this.$options = options;
}
}
// 插件实现install方法, 注册$router
VueRouter.install = function (_vue) {
Vue = _Vue;
// 任务2 挂载$router
// 为什么要使用混入的方式. 主要原因是vue.use代码在前,Router实例创建在后. 而install逻辑又需要使用到该实例
Vue.mixin({
beforeCreated(){
// 只有根组件拥有router选项
if (this.$options.router) {
Vue.prototype.$router = this.$options.router;
}
}
})
// 任务2 实现两个全局组件router-link router-view
Vue.component('router-link',Link);
Vue.component('router-view',View);
}
export default VueRouter
实现router-link组件
<router-link to="/">点击</router-link>
Vue.component('router-link', {
props: {
to: {
type: String,
required: true
}
},
render (h) {
return h('a', {attrs: '#' + this.to}, this.$slots.default)
}
})
实现router-view组件
Vue.component('router-view', {
render(h) {
// 暂时不渲染任何内容
return h(null)
}
})
监控url变化
定义响应式的current属性, 监听hashChange事件
class VueRouter {
constructor(options) {
// 定义响应式的属性current
const initial = window.location.hash.slice('#') || '/';
Vue.util.defineReactive(this, 'current', initial);
// 监听hash变化
window.addEventListener('hashchange', this.onHashChange.bind(this));
// 缓存path和route映射关系
this.routerMap = {};
this.$options.routes.forEach(route => {
this.routerMap[route.path] = route;
})
}
onHashChange(){
this.current = window.location.hash.splice(1);
}
}
// router-view
Vue.component('router-view', {
render(h) {
const {routerMap , current} = this.$router;
const component = routerMap[current] ? routerMap[current].component : nu~~~~ll;
return h(component)
}
})
完整vue-router简单实现代码
let Vue;
class VueRouter {
constructor(options) {
this.$options = options;
// 把current作为相应式数据
// 将来发送变化, router-view的render函数能够再次执行
this.current = '/';
const initial = window.location.hash.slice("#") || '/'
Vue.util.defineReactive(this, 'current', initial)
// 监听hash变化
window.addEventListener('hashchange', () => {
this.current = window.location.hash.slice(1);
})
// 缓存path和route映射关系
this.routerMap = {};
this.$options.routes.forEach(route => {
this.routerMap[route.path] = route
});
console.log(this.routerMap);
}
}
// _vue 是vue.use调用时传入的
// 全局混入的目的: 延迟下面逻辑到router创建完毕并且 附加到选项上时才执行
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', {
props: {
to: {
type: String,
required: true
}
},
render (h) {
// 使用插槽动态拿到组件包含的文案
return h(
'a',
{
attrs:{
href: '#'+this.to
}
},
this.$slots.default)
},
});
Vue.component('router-view', {
render(h) {
// 获取当前路由对应的组件
const { routerMap, current} = this.$router;
const component = routerMap[current] ? routerMap[current].component: null;
return h(component)
},
});
}
export default VueRouter
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。