Vue-router中hash模式和history模式

一、路由

1.前端路由

  • Hash:使用url中的hash(#后面的參數(shù))來作為路由,通過監(jiān)聽hash變化找到對應組件中內容更新到頁面中去。支持所有瀏覽器。
  • History:使用HTML5 History API 和服務器配置。參考官網(wǎng)中HTML5 History模式。有兼容性,支持特定瀏覽器。

2.后端路由

  • 直接訪問url,向服務器請求資源。

3.前后端路由區(qū)別

  • 后端路由向服務器發(fā)出請求。
  • 前端路由修改視圖時,不會向服務器發(fā)出請求。
二、hash模式和history模式的區(qū)別

1.hash

  • 即地址欄 URL 中的 # 符號(此 hash 不是密碼學里的散列運算)。比如這個 URL:http://www.baidu.com/#/hello,hash 的值為 #/hello。利用 location.hash和window.addEventListener('hashchange,()=>{})方法獲取和監(jiān)聽hash值。它的特點在于:hash 雖然出現(xiàn)在 URL 中,修改hash不會向服務器發(fā)送http請求,因此改變 hash 不會重新加載頁面。
  • 符號#夾雜在 URL 里看起來確實有些不太美麗
  • 兼容性好,所有瀏覽器都支持
  • hash 只可添加短字符串
  • hash 模式下,僅 hash 符號之前的內容會被包含在請求中,因此對于后端來說,即使沒有做到對路由的全覆蓋,也不會返回 404 錯誤

2.history

  • 利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。(需要特定瀏覽器支持)這兩個方法應用于瀏覽器的歷史記錄棧,在當前已有的 back、forward、go 的基礎之上,它們提供了對歷史記錄進行修改的功能。只是當它們執(zhí)行修改時,雖然改變了當前的 URL,但瀏覽器不會立即向后端發(fā)送請求。
  • 沒有符號#,看起來優(yōu)雅很多。
  • 兼容指定瀏覽器。
  • pushState() 通過 stateObject 參數(shù)可以添加任意類型的數(shù)據(jù)到記錄中
  • 用戶手動輸入 URL 后回車,或者刷新(重啟)瀏覽器的時候跳轉后刷新或者回跳,會報一個404的錯誤,找不到指定的路由,所以后端將所有請求都強制重定向到首頁,相當于服務端屏蔽了訪問資源不存在的情況,而將路由的工作留給客戶端自己去處理,這樣啟用了history模式的前端路由在直接定位到子頁面時就不會報錯了。
  • 當服務端重定向后,如果沒有進行SSR的同構路由定制,對于所有路由請求都會返回index.html頁面,此時如果需要使用404頁面,就需要在客戶端路由中設定一個優(yōu)先級最低的兜底路由,由于優(yōu)先級的緣故,它不會影響其他精確匹配的路由配置:
const router = new VueRouter({
  mode: 'history',
  routes: [
    { path: '*', component: NotFoundComponent }
  ]
})
三、實現(xiàn)一個簡單hash路由(沒有支持子路由哦~)
class HistoryRoute{
    constructor(){
        this.current=null
    }
}
class vueRouter{
    constructor(options){
        this.mode=options.mode||'hash';
        this.routes=options.routes||[];
        this.routesMap=this.createMap(this.routes);
        this.history=new HistoryRoute;
        this.init();
    }
    init(){//獲取當前current路徑
        if(this.mode=='hash'){
            //自動加#
            location.hash?'':location.hash='/'
        }
        window.addEventListener('load',()=>{
            this.history.current=location.hash.slice(1)//獲取#后面值
        })
        window.addEventListener('hashchange',()=>{//監(jiān)聽hash改變
            this.history.current=location.hash.slice(1)
        })
    }
        //將routes中路徑和組件以鍵值對關聯(lián)起來
    createMap(routes){
        return routes.reduce((memo,current)=>{
            memo[current.path]=current.component
            return memo
        },{})
    }
}
vueRouter.install=function(Vue){
    if(vueRouter.install.installed)return //判斷插件是否已注冊
    vueRouter.install.installed=true
    Vue.mixin({
        beforeCreate(){//實現(xiàn)雙向數(shù)據(jù)綁定
            if(this.$options && this.$options.router){
                this._root=this
                this._router=this.$options.router;
                Vue.util.defineReactive(this,'current',this._router.history)
            }else{
                this._root=this.$parent._root
            }
            //$router不可修改
            Object.defineProperty(this,"$router",{
                get(){
                    return this._root._router;
                },
            })
            
        },
    })
    Vue.component('router-view',{//注冊組件
        render(h){
            console.log(this._self)
            var current=this._self._root._router.history.current
            var routesMap=this._self._root._router.routesMap
            return h(routesMap[current])//渲染組件
        }
    })
}
export default vueRouter;
四、總結
  • hash 模式和 history 模式都屬于瀏覽器自身的特性,Vue-Router 只是利用了這兩個特性(通過調用瀏覽器提供的接口)結合注冊Vue全局插件、注冊Vue全局組件(router-view)等技術來實現(xiàn)前端路由。對于一般的 Vue + Vue-Router + Webpack + XXX 形式的 Web 開發(fā)場景,用 history 模式即可,只需在后端(Apache 或 Nginx)進行簡單的路由配置,同時搭配前端路由的 404 頁面支持,畢竟以美為主嘛,哈哈~。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容