最近看了一些教學,做爲本身的總結一下。實現一下low 版本Vue-routerjavascript
install
方法,詳情參考這裏constructor
須要接收一個對象router-link
,router-view
,須要全局註冊router-link
,router-view
這兩個方法options
的參數。還有對應的三個方法,分別執行 第一步4中的事情,仍是實現install
方法let Vue // 先定義定義一個Vue
class MyVueRouter {
constructor (options) { // 在建立實例的時候會接受一個配置項
this.$options = options
this.routeMap = {} // 後面會說
// 路由響應式 強綁定,這就是與 react 裏面router區別的緣由 只能用於Vue
this.app = new Vue({
data: {
current: '/'
}
})
}
init () {
this.bindEvents() // 監聽 url變化,綁定事件
this.createRouterMap(this.$options) // 解析路由配置
this.initComponent() // 實現router-view 那兩個組件
}
bindEvents () { // 監聽 url變化
}
onHashChange () { // 解析路由配置
}
createRouterMap (options) { // 實現router-view 那兩個組件
}
initComponent () {
// router-link router-view
Vue.component('router-link', {
}
})
// router-view
Vue.component('router-view', {
}
}
複製代碼
說一下上面爲何要new Vue()
,咱們須要一個值來 記錄當前的地址欄current
,因此這裏面就用到了Vue的特性。這就是Vue-router只能用在Vue不能用在其餘語言中的緣由html
// 做爲建立
MyVueRouter.install = function (_vue) { // 做爲插件 實際執行的是這個方法 在執行過程當中會返回一個Vue實例
Vue = _vue
Vue.mixin({ // 擴展組件
beforeCreate () {
// this 是當前Vue實例
if (this.$options.router) {
// 在跟組件執行一次
Vue.prototype.$router = this.$options.router
this.$options.router.init()
}
}
})
}
// 使用組件
Vue.use(MyVueRouter)
複製代碼
首先理清楚這個方法的做用就是,監聽url的變化。當url變化的時候執行指定的方法/函數vue
bindEvents () {
// 監聽剛打開頁面的時候 注意綁定this指向
window.addEventListener('load', this.onHashChange.bind(this))
// 監聽剛url變化的時候
window.addEventListener('hashchange', this.onHashChange.bind(this))
}
複製代碼
經常使用事件的網址,須要的你們自行點擊 這裏 ,注意 不須要加onjava
onHashChange () {
this.app.current = window.location.hash.slice(1) || '/'
// 方便你們看到全部改變 打印的日誌
console.log(this.app.current)
console.log(window.location.hash)
}
複製代碼
這個沒什麼解釋的,就是利用改變Vue的響應, 改變current
node
爲何要從1位開始?react
hash路由,前面有# 詳細請看 打印日誌vue-router
做用 解析路由配置,讓其一一對應api
這時在上面建立的routeMap
就有用了app
createRouterMap (options) {
options.routes.forEach(item => {
this.routeMap[item.path] = item.component
})
}
複製代碼
建立鍵值對,使component
和路由current
一一對應框架
做用 實現router-link
,router-view
這兩個方法
initComponent () {
// router-link router-view
Vue.component('router-link', {
props: { to: String },
render (createElement) {
// createElement 參數 tag data(可選) children attrs原生的html屬性 this.$slots.default a標籤裏面的文字
return createElement('a', { attrs: { href: '#' + this.to } }, [this.$slots.default])
// 返回Vnode 虛擬dom
}
})
// router-view
Vue.component('router-view', {
render: (h) => { // h createElement簡寫 用件頭函數 改變了this指向
// 全局組件 跟全局vue有關 裏面屬性發生變化
const comp = this.routeMap[this.app.current]
// comp 拿到了對應的組件
return h(comp)
}
})
}
複製代碼
有關 createElement的詳情,請點擊這裏
有關render 函數,請點擊 這裏
首先進行全局註冊
接受一個參數 props:{to: String}
平時使用的是這樣使用,若是有須要多加一些,這裏只實現這一個
<router-link to="/">Home</router-link>
由於 router-link
最主要做用是跳轉,因此咱們建立一個a標籤
,配置跳轉信息來實現跳轉
注意,這裏面使用的是箭頭函數,不是普通函數,目的,解決this指向問題
由於使用的過程當中不須要參數,因此不用寫props
咱們只須要拿到當前current
對應的,拿到對應的模板,交給createElement渲染就行
import a from './../components/a'
import b from './../components/b'
// url變化 路由解析 組件配置
class MyVueRouter {
constructor (options) { // 在建立實例的時候會接受一個配置項
this.$options = options
this.routeMap = {}
// 路由響應式 強綁定,這就是與 react 裏面router區別的緣由 只能用於Vue
this.app = new Vue({
data: {
current: '/form'
}
})
}
init () {
this.bindEvents() // 監聽 url變化
this.createRouterMap(this.$options) // 解析路由配置
this.initComponent() // 實現router-view 那兩個組件
}
bindEvents () {
window.addEventListener('load', this.onHashChange.bind(this))
window.addEventListener('hashchange', this.onHashChange.bind(this))
}
onHashChange () {
this.app.current = window.location.hash.slice(1) || '/'
console.log(this.app.current)
console.log(window.location.hash)
}
createRouterMap (options) {
options.routes.forEach(item => {
this.routeMap[item.path] = item.component
})
}
initComponent () {
// router-link router-view
Vue.component('router-link', {
props: { to: String },
render (createElement) {
// createElement 參數 tag data(可選) children attrs原生的html屬性 this.$slots.default a標籤裏面的文字
return createElement('a', { attrs: { href: '#' + this.to } }, [this.$slots.default])
}
})
// router-view
Vue.component('router-view', {
render: (h) => {
// h createElement縮寫 用件頭函數 改變了this指向 // 全局組件 跟全局vue有關 裏面屬性發生變化
const comp = this.routeMap[this.app.current]
console.log(comp)
return h(comp)
}
})
}
}
// 做爲建立
MyVueRouter.install = function (Vue) {
// 做爲插件 實際執行的是這個方法
// 是能夠收到一個Vue實例
Vue.mixin({ // 擴展組件
beforeCreate () {
// this 是當前Vue實例
if (this.$options.router) {
// 在跟組件執行一次
Vue.prototype.$router = this.$options.router
this.$options.router.init()
}
}
})
}
Vue.use(MyVueRouter)
export default new MyVueRouter({
routes: [
{
path: '/',
name: 'A',
component: a
},
{
path: '/b',
name: 'B',
component: b
}
]
})
複製代碼
<template>
<div id="app">
<router-link to="/">Home</router-link> |
<router-link to="/b">B</router-link> |
<router-view></router-view>
</div>
</template>
複製代碼