Vue-router

編程式導航

1 .用在可復用的路由視圖里面趣竣,比如所有的需要跳轉到一個文章具體內容的路由辖源,每一次跳轉到新路由的時候输枯,其實傳的東西都是這個文章的id,在里面再次進行請求嚼贡,別的東西都是一樣的,還有就是在這個情況下返回娘扩。
2 .本質就是監(jiān)聽URL的變化着茸,然后匹配路由規(guī)則,顯示相應的頁面琐旁,而且無需刷新涮阔。

代碼實現(xiàn)方面

哈希路由

1 .通過location.hash獲取到網址#號后面的網頁位置標識符
2 .onhashchange事件來監(jiān)聽哈希的變化然后執(zhí)行響應的回調函數(shù)
3 .不同的#值,表示不同的訪問狀態(tài)灰殴,向用戶發(fā)出某個狀態(tài)的訪問鏈接,也就是說用所有的哈希值來索引到具體顯示的某一個頁面
4 .代碼

// 對window事件進行包裝和兼容

// 兩種思路吧敬特,一種就是直接使用next,pre這樣的指針來指定,一種就是把所有的操作都放到一個棧里面验懊。
const addEvent=(function(){
    if(window.addEventListener){
        return function(ele,event,handle,isBuble){
            isBuble=isBuble||false
            ele.addEventListener(event,handle,isBuble)
        }
    }else if(window.attachEvent){
        return function(ele,event,handle){
            ele.attachEvent('on'+event,handle)
        }
    }else{
        return function(ele,event,handle){
            return function(ele,event,handle){
                ele['on'+event]=handle
            }
        }
    }
})()

class Router{  
    constructor(){
        // this.routers={}
        // this.pre=this.pre||null
        // this.next=this.next||null
        // 不是必須

        // 也就是說當定義一個和系統(tǒng)api相關的類的時候擅羞,


        this.currentUrl=null
        this.currentIndex=null
        this.routerArr=[]
        this.len=0
        this.canpush=true
//一個是否記錄的開關,現(xiàn)在就是go义图,和back的所有操作都不會記錄减俏,只會記錄點擊的歷史記錄,就是因為如果要記錄go碱工,和back的操作的話娃承,可能會造成死循環(huán)。
        window.addEventListener('load',()=>{
            this.updateUrl()
        })
        // 這個是關鍵怕篷。這個類需要檢測的東西也可以加在這里么历筝?
//constructor里面竟然也可以加這個東西,真的奇怪廊谓,類這個東西還得探索一下其他的功能
        window.addEventListener('hashchange',()=>{
            if(this.canpush){
                this.updateUrl()
            }else{
                console.log('')
            }
        })
    }
   
    // 初始化route梳猪,以及更新路由
    updateUrl(){
        this.currentUrl=window.location.hash.slice(1)||'/'
        this.routerArr.push(this.currentUrl)
        this.len=this.routerArr.length
        this.currentIndex=this.routerArr.length-1
        this.canpush=true
    }
    back(){
        console.log('back')
        console.log(this)
        this.canpush=false
        if(this.currentIndex==0){
            window.location.hash='#'+this.routerArr[this.len-1]
            this.currentIndex=this.len-1
        }else{
            window.location.hash='#'+this.routerArr[this.currentIndex-1]
            this.currentIndex--
        }
    }
    go(){
        // 還需要計算下沒有進行記錄的時候做了前進點擊
        console.log('go')
        console.log(this)
        this.canpush=false
        if(this.currentIndex==this.len-1){
            window.location.hash='#'+this.routerArr[0]
            this.currentIndex=0
        }else{
            window.location.hash='#'+this.routerArr[this.currentIndex+1]
            this.currentIndex++
        }
    }
}

5 .但是這個只能做一些前后倒退的簡單操作,想要一一對應起來蒸痹,的需要key-value形式的數(shù)據結構
6 .或者是最后渲染出來的頁面春弥,真正自己構造路由的時候還是想要上面那種結果呛哟,感覺這個適合服務端渲染,每一個或者每一種情況渲染出來的頁面對應著唯一的哈希url
7 .升級改造的話匿沛,其實數(shù)組里面應該是這樣的,記錄頁面的訪問次數(shù)扫责,訪問順序。

{
hash:'/',
count:1
}

history路由

1 .缺點:pushState逃呼,replaceState只會對url進行改變鳖孤,不會觸發(fā)頁面刷新,只是導致history對象發(fā)生變化抡笼,不能跨域苏揣。這就導致如果直接輸入url,但是后端沒有處理的話蔫缸,直接是404腿准,哈希路由可以定位到某個具體的dom
2 .代碼

3 .怎么樣升級下既能用上哈希的準確性,有可以方便使用的時候傳入key-value的一個地址對應組件的操作
4 .點擊一個地址的時候拾碌,現(xiàn)在我傳入的數(shù)組里面找我是否定義了這個地址對應的組件,如果沒有街望,可以選擇定義新的地址然后加入校翔,也可以彈出報錯,把這個加入
5 .還是想做的就是go.back不記錄到歷史記錄里面灾前。
6 .整個思路其實是這樣的防症,router-link之類的標簽點擊觸發(fā)的時候,先在router傳入的對象里面去尋找哎甲,是否有對應的組件來展示對應的路由地址
7 .那其實這個升級版的路由其實有兩個功能蔫敲,一個是存儲歷史記錄,一個是顯示對應的組件炭玫,上一個路由組件需要存儲功能我們交給了history API奈嘿,但是這個api是不會保存和組件有關的操作,所以我們需要把和組件有關的歷史記錄人為的添加到這個api里面
8 .代碼


window.history的簡單方法

1 .history.length:當前窗口訪問過網址的數(shù)量
2 .history.state:history堆棧最上層的狀態(tài)值
3 .history.back():前一個網址
4 .history.forward():移動到下一個網址吞加。
5 .history.go(n):以當前網址為基準裙犹,進行移動。正數(shù)為前衔憨,負數(shù)為后叶圃。0的話相當于刷新當前頁面。
6 .window.history.pushState(state,title,url)
7 .最后一個url必須是同一域名的url践图,不然會認為是有安全隱患
8 .pushState是不會觸發(fā)刷新頁面掺冠,只是導致history對象發(fā)生變化,地址欄會有反應
9 .history.replaceState()修改當前history的記錄码党,參數(shù)和上個函數(shù)的一樣
10 .特殊事件:popstate,用戶點擊前進德崭,后退按鈕悍及,或者使用js調用History.back(),History.go(),History.forward()方法才會觸發(fā),而且這個事件只針對同一個文檔接癌,如果瀏覽歷史發(fā)生了改變心赶,導致加載了不同的文檔,事件也不會觸發(fā)缺猛,事件的回調參數(shù)就是以上兩個方法傳入的第一個參數(shù)缨叫。

window.onpopstate = function (event) {
  console.log('location: ' + document.location);
  console.log('state: ' + JSON.stringify(event.state));
};

// 或者
window.addEventListener('popstate', function(event) {
  console.log('location: ' + document.location);
  console.log('state: ' + JSON.stringify(event.state));
});

組件源碼分析

Vue.use

1 .在Vue路由里面增加覆蓋所有情況的候選資源,如果url匹配不到任何資源荔燎,返回一個404頁面
2 .使用方法:每一個路由映射一個組件
3 .Vue.use(router):將組件插入到Vue中去耻姥,use方法會檢測組件內是否有install方法,如果有的話有咨,執(zhí)行install方法
4 .對于路由注冊來說琐簇,核心就是調用Vue.use(vueRouter),使VueRouter可以調用Vue,然后通過Vue來調用VueRouter的install函數(shù)座享,在該函數(shù)中婉商,核心就是給組件混入鉤子函數(shù)和全局注冊兩個路由組件
5 .全局混合方法來初始化VueRouter
6 .給當下所有組件注入router和route對象

install

1 .對插入組件在beforecreate鉤子操作,在Vue聲明周期階段就可以調用到組件的相關方法
2 .通過Vue.prototype定義router,route屬性渣叛,這樣所有的組件都可以獲取到這兩個屬性
3 .Vue上注冊router-link,router-view組件

生成router實例

1 .根據配置數(shù)組生成路由配置記錄表
2 .根據不同的模式生成監(jiān)控路由變化的History對象
3 .創(chuàng)建一個路由匹配對象丈秩,根據mode來踩去不同的路由方式

生成Vue實例

1 .把router傳入new Vue()中
2 .進入Vue的生命周期,執(zhí)行第一步router對Vue混入beforeCreate鉤子函數(shù)淳衙,判斷實例化的options是否包含routr-為組件的router-view組件渲染提供$route蘑秽,保證router.init只被調用一次
3 .初始化結束,界面將顯示默認首頁
4 .當根組件調用beforeCreate鉤子函數(shù)的時候箫攀。初始化路由肠牲,因為只有根組件會有router屬性
5 .在路由初始化的時候,核心就是i進行路由的跳轉靴跛,改變URL然后渲染對應的組件缀雳。

路由更新方式

1 .router-link綁定的click方法,觸發(fā)history.push或者history.replace汤求,從而進行路由轉換俏险,更新路由。在BeforeCreate有劫持_route方法扬绪,當_route發(fā)生變化后竖独,router-view自動變化。
2 .地址變化:HashHistory或者HTMLHistory會自動監(jiān)控hashchange和popState來對路由變化做處理挤牛,從而執(zhí)行上面那一套程序莹痢。

Vue插件機制

1 .

組件特殊方法

1 .this.router:返回總的路由器 2 .this.route:返回當前路由

動態(tài)路由

1 .不僅僅是具體的歌曲頁面可以使用這個功能,某種模式全需要匹配到一個路由,就好像一個帶子可以把雜亂的路由全都梳理起來竞膳,只不過這個使用之后無法在每個具體的路徑下面在添加子路徑航瞭,所以這個一般才會用在最末端的路徑。
2 ./user/:username/post/:post_id 他是可以分段約束的坦辟。這樣有更大的靈活性刊侯。這樣上面那個問題應該可以解決了。那這個可以隨便用了锉走,只不過還是需要一些約束滨彻,可以看下別人路由是如何設計的
3 .可以變化的那些路徑參數(shù)都是可以在this.$router.params里面訪問到,這個如果是漢字的路徑參數(shù)的話挪蹭,是可以直接在組件里面顯示的亭饵,但是如果是英文的話,還需要一個映射表梁厉。
4 .這個還是有局限性辜羊,雖然路徑是可以類似的正則匹配到,但是組件是只能對應一個的词顾。所以還是還是需要拆開八秃。他適用的是一套模板但是對應不同數(shù)據的情況,轉到對應的界面之前计技,把請求的資源的標記存到vuex里面喜德,到了這個組件里面開始ajax請求,填充頁面內容垮媒。
5 .這樣又出現(xiàn)個問題,路由參數(shù)變化的時候航棱,對應組件勢力會被復用睡雇,比起銷毀在創(chuàng)建,復用更加高效饮醇。此時組件的生命周期是不會被調用的它抱,那么mounted里面定義的函數(shù)可能不會初始化,所以需要watch監(jiān)視下路由參數(shù)的響應朴艰,一旦發(fā)生變化观蓄,而且符合變化的條件,那就進行初始化祠墅。
6 .匹配優(yōu)先級是按照定義的位置順序來算的侮穿,先到先匹配

編程式導航

1 .this.$router.push('home') 它實現(xiàn)的效果和router-link實現(xiàn)的方式一樣。
2 .適用場景:返回操作毁嗦,只是知道下一步要怎么操作亲茅,但是沒有具體的地址,或者在頁面上不方便表現(xiàn)出來操作的UI,就需要在底層使用編程導航
3 .編程式導航的語法完全類似于window.history語法
4 .

命名路由

1 .在index里面給特殊的路由加上name克锣,這樣在跳轉的時候就會很方便茵肃,比如跳轉到首頁以及重定向的時候。
2 .一張頁面需要顯示多個路由窗口的時候袭祟。類似iframe的效果
3 .這個時候使用編程式導航的時候傳參數(shù)的時候非常方便
4 .鏈接的時候傳的是數(shù)組验残,里面有name關鍵字一般的傳的是path
5 .編程式導航的時候也是push這樣的數(shù)組參數(shù)
6 .

命名視圖

1 .components:{default:}默認參數(shù)
2 .router-view 里面有name屬性。
3 .components:里面?zhèn)魅雽慕M件數(shù)組 name:組件名

重定向巾乳,別名

1 .redirect:訪問當前路由地址的時候您没,重定向到另一個路由地址下的視圖
2 .alais:給任意一個路由加一個這參數(shù),起個名字想鹰,然后直接router-link 的to就可以過來
3 .那別名和命名路由的區(qū)別是什么紊婉?看理論感覺用法差不多,還是實踐下看看差距在哪里吧辑舷。

重要api

router-link

1 .無論是HTML history模式還是hash模式喻犁,行為表現(xiàn)一致。切換路由模式的時候何缓,無需做任何的改動
2 .在html history模式下肢础,roter-link會令守衛(wèi)點擊事件,讓瀏覽器不在加載頁面
3 .在hisitory下使用base選項之后碌廓,所有的to屬性都不需要寫(基路徑)了传轰。
4 .to:當路由目標被點擊后,會立刻把to的值傳到router.push()谷婆,這個值可以是一個字符串或者描述目標位置的對象,那這樣我們在寫組件的時候其實可以是任意一個值慨蛙,只要他有to這個傳入屬性,那么就可以點擊觸發(fā)router.push函數(shù)進行路由轉換

1 .可以使用v-bind:傳入動態(tài)參數(shù)纪挎,比如動態(tài)渲染一個樹形導航
2 .傳入對象的時候期贫,可以是path,name,path+query

5 .replace參數(shù):設置replace的話,點擊的對象异袄,進行跳轉的時候不記錄歷史記錄
6 .append:相對于傳入的路徑前面添加一個基路徑通砍,這個基路徑是什么?
7 .tag:‘router-link渲染出什么結果’烤蜕,默認是a標簽
8 .router-link-active:選中的時候自動給標簽價加上這個樣式封孙,你可以把想定義的樣式放在這個里面
9 .event:觸發(fā)的事件,默認是click
10 .exact:這個看文檔看不懂讽营。
11 .exact-active-class:

router-view

1 .因為他也是個組件虎忌,所以可以配合transition,keepalive使用斑匪,如果兩個一起使用呐籽,確保內層使用keep-alive
2 .name:router-view設置了名稱锋勺,則會渲染對應路由配置中conponents中下的對應組件

index.js文件里面

routes

1 .path
2 .components
3 .component
4 .redirect
5 .alias
6 .props
7 .children
8 .meta
9 .beforeEnter
10 .caseSencetive:是否對匹配規(guī)則大小敏感
11 .pathToregexOptions:object編譯匹配正則的選項

mode

1 .hash:使用URL hash值來做路由,支持所有瀏覽器
2 .history:依賴HTML History和服務器配置狡蝶。需要后臺支持庶橱,如果后臺沒有配置對應的路由,就會返回404贪惹,所以必須增加一個能夠覆蓋所有情況的候選資源苏章,如果url匹配不到任何靜態(tài)資源,返回一個默認的頁面奏瞬。這個需要前端和后端來把保證對url資源的共同配置枫绅。

base:應用的基礎路徑。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末硼端,一起剝皮案震驚了整個濱河市并淋,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌珍昨,老刑警劉巖县耽,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異镣典,居然都是意外死亡兔毙,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門兄春,熙熙樓的掌柜王于貴愁眉苦臉地迎上來澎剥,“玉大人,你說我怎么就攤上這事赶舆⊙埔Γ” “怎么了?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵芜茵,是天一觀的道長蜻懦。 經常有香客問我,道長夕晓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任悠咱,我火速辦了婚禮蒸辆,結果婚禮上,老公的妹妹穿的比我還像新娘析既。我一直安慰自己躬贡,他們只是感情好,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布眼坏。 她就那樣靜靜地躺著拂玻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上檐蚜,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天魄懂,我揣著相機與錄音,去河邊找鬼闯第。 笑死市栗,一個胖子當著我的面吹牛,可吹牛的內容都是我干的咳短。 我是一名探鬼主播填帽,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼咙好!你這毒婦竟也來了篡腌?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤勾效,失蹤者是張志新(化名)和其女友劉穎嘹悼,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體葵第,經...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡绘迁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了卒密。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缀台。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖哮奇,靈堂內的尸體忽然破棺而出膛腐,到底是詐尸還是另有隱情,我是刑警寧澤鼎俘,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布哲身,位于F島的核電站,受9級特大地震影響贸伐,放射性物質發(fā)生泄漏勘天。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一捉邢、第九天 我趴在偏房一處隱蔽的房頂上張望脯丝。 院中可真熱鬧,春花似錦伏伐、人聲如沸宠进。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽材蹬。三九已至实幕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間堤器,已是汗流浹背昆庇。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留吼旧,地道東北人凰锡。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像圈暗,于是被迫代替她去往敵國和親掂为。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內容