vue-router用法
首先簡單看看vue-router簡單用法:
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import Vue from 'vue'
// route.js
const routes = [
{ path: '/',component: Home },
{ path: '/about',component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
]
Vue.use(VueRouter)
export default route = new VueRouter({
routes
})
// main.js
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
// app.js
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<router-view/>
</div>
</template>
<script>
export default {
name: 'app',
}
</script>
從上面代碼可以看到笆载,在route.js中導(dǎo)出了實例化路由對象待秃,通過vue.use之后便可以在所有組件中訪問到$router,并且可以使用router--link嗅辣、router-view
,并且可以響應(yīng)路由變化更新vue渲染蜻势,下面帶大家手動錄一個vue路由組件有巧,來揭開vueRouter的神秘面紗
動手擼一個VueHashRouter
1.新建vueHashRouter.js
文件,實現(xiàn)構(gòu)造函數(shù):
// vueHashRouter.js
export class VueHashRouter {
constructor(options){
this.$options = options // 保存一下傳入的路由配置選項
this.routeMap = {} // 映射路由和組件實例
}
2. 實現(xiàn)install接口:
// vueHashRouter.js
export class VueHashRouter {
//some codes
}
// 實現(xiàn)install接口
VueHashRouter.install = (Vue) => {
// 混入
Vue.mixin({
//組件創(chuàng)建時注入實例
beforeCreate:() => {
// 僅在跟組件創(chuàng)建時 執(zhí)行一次
if(this.$options.router){
// 將跟組件options上面的router實例 掛在原型上
Vue.prototype.$router = this.$options.router
// 執(zhí)行init方法
this.$router.init()
}
}
})
}
調(diào)用Vue.use()
就會執(zhí)行install
方法, 這里先混入beforeCreate
生命周期芬膝,這樣里面的代碼就會隨著生命周期一塊執(zhí)行望门,并且判斷if(this.$options.router)
,因為創(chuàng)建跟組件時傳入了router實例:
new Vue({
router,
store,
...
}).mount('#app')
這個判斷找到的就是這個實例, 我們只需要在這個組件創(chuàng)建時執(zhí)行一次:
- 把router實例掛在Vue原型上
- 執(zhí)行實例的初始化方法
這里就解答了為啥每個vue組件內(nèi)部都有個$router對象了
3. 初始化router
接下來我們來實現(xiàn)init
方法锰霜,在init方法里面做了三件事情:
- 綁定路由change事件
- 解析路由配置
- 注冊全局組件
router-link筹误、router-view
代碼如下:
// vueHashRouter.js
export class VueHashRouter {
...
init(){
this.bindEvents() // 監(jiān)聽事件
this.createRouteMap(this.$options) // 解析路由配置
this.initComponent() // 初始化兩個組件: router-view, router-link
}
bindEvents = () => {
// 利用vue雙向綁定 監(jiān)聽hash變化出發(fā)重新渲染
this.app = new Vue({
data: { current: '/' }
})
window.addEventListener('load', this.onHashChange)
window.addEventListener('hashchange', this.onHashChange)
}
onHashChange = () => {
this.app.current = window.location.hash.slice(1)
}
createRouteMap = (options) => {
options.routes.forEach(route => this.routeMap[route.path] = route.component)
}
initComponent = () => {
// 直接全局注冊組件 router-view, router-link
Vue.component('router-link', {
props: { to : String },
render: function(h){
// this指向當前router-link實例
return h('a', { attrs: { href: '#' + this.to}}, [this.$slots.default])
}
})
Vue.component('router-view', {
// 注意這里是箭頭函數(shù)
render: (h) => {
let comp = this.routeMap[this.app.current]
return h(comp)
}
})
}
bindEvents
就是進行了一個路由change事件的監(jiān)聽,并強制綁定vue的實例上, 然后讓這個實例跟router-view
關(guān)聯(lián)癣缅, 只要hash發(fā)生變化厨剪, 就會觸發(fā)router-view
的渲染更新
initComponent
的作用就是全局注冊兩個路由組件,這樣我們就可以直接在模板中使用了友存。
注意:這里還沒有處理路由嵌套祷膳,還不能使用嵌套路由
到這里就已經(jīng)完成了一個簡單的vue的router組件,雖然只實現(xiàn)了hash路由屡立,稍作修改也可以實現(xiàn)browser路由和更加復(fù)雜的路由配置