vue-router做爲vue全局桶的一個核心類庫, 其實現方式, 有着不少巧妙之處, 你是否真正瞭解呢?javascript
最簡單的是經過cli安裝一個vue-router插件, 會自動的修改咱們項目的代碼, 正確的使用vue-router. 一條命令搞定.vue
vue add router
複製代碼
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
]
const router = new VueRouter({
routes
})
export default router
複製代碼
import Vue from 'vue'
import App from './App.vue'
import router from './router';
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')
複製代碼
看起來是否很簡單? 答案是確定的. 由於以上步驟都是安裝vue-router插件時, 會自動幫咱們添加的.java
lib/x-vue-router.jsnode
/** * - 建立一個插件 * - vueRouter是一個class, 能夠new一個實例 * - $router掛載到vue的原型上. * - 監聽hash變化, 能夠及時響應 * - router-link, router-view兩個全局組件 */
let Vue;
class XVueRouter {
constructor(options) {
this.$options = options;
// 保存path和組件的對應關係.
this.routeMap = {};
// 使用vue來作數據響應式. curren保存當前的url hash
// 一旦hash發生改變, 經過onHashChange更改current值, 對應的router-view組件的
// render方法就會被從新執行(也就是新的組件就會從新渲染, 路徑切換成功).
this.vm = new Vue({
data: {
current: '/'
}
});
this.onHashChange = this.onHashChange.bind(this);
}
init() {
// hashchange
this.bindEvents();
// 初始化path和組件的鍵值對
this.initRouteMap();
// 添加router-link, router-view組件.
this.createGlobalComponent();
}
bindEvents() {
window.addEventListener('hashchange', this.onHashChange);
window.addEventListener('load', this.onHashChange);
}
initRouteMap() {
this.$options.routes.forEach(m => this.routeMap[m.path] = m.component);
}
onHashChange() {
// #/about -> /about
this.vm.current = window.location.hash.slice(1) || '/';
}
createGlobalComponent() {
Vue.component('router-link', {
props: { to: { type: String, required: true } },
render() {
return <a href={`#${this.to}`}>{this.$slots.default}</a>;
}
});
Vue.component('router-view', {
render: h => h(this.routeMap[this.vm.current])
});
}
}
/** * 建立一個新插件. 實現一個靜態的install方法. */
XVueRouter.install = function (_Vue) {
// 經過Vue.use方法來安裝插件時, 會傳入一個Vue構造器.
Vue = _Vue;
// 調用vue的mixin方法, 在組件的beforeCreate生命週期中
// 初始化vueRouter.
Vue.mixin({
beforeCreate() {
// this指向的是組件的實例(這裏解析了爲何要在跟組件中傳入router實例.)
if (this.$options.router) {
// 1. 將$router掛載到vue的原型, 方便組件內部直接調用.
Vue.prototype.$router = this.$options.router;
// 2. 初始化vueRouter.
this.$options.router.init();
}
}
})
}
export default XVueRouter;
複製代碼
demowebpack