關于前端路由

什么是路由

簡單來說路由就是用來跟后端服務器進行交互的一種方式,通過不同的路徑,來請求不同的資源(if...else...),給我一個路徑,我給你返回一個響應,請求不同的頁面是路由的其中一種功能。

前端路由

我們通過一個狀態切換的例子來理解前端路由,代碼如下:

  // HTML
  <x-tab>
    <ol class="nav">
      <li>tab 1</li>
      <li>tab 2</li>
    </ol>
    <ol class="content">
      <li>content 1</li>
      <li>content 2</li>
    </ol>
  </x-tab>

  // CSS
  x-tab{ display: block; }
  x-tab > .nav > li.active{ background: red; }
  x-tab > .content > li{ display: none; }
  x-tab > .content > li.active{ display: block; }

  // js(引入jquery)
  $('x-tab').on('click', '.nav > li', (e)=>{
    let $li = $(e.currentTarget);
    $li.addClass('active').siblings().removeClass('active');
    let index = $li.index();
    $li.closest('x-tab').find('.content > li').eq(index).addClass('active')
      .siblings().removeClass('active')
  })

這樣實現了點擊tab-1,出現對應的 content-1 的內容,點擊tab-2,出現對應的 content-2 的內容的功能。

現在,我們先設置 tab-1的狀態為 active,content-1 也為 active。刷新頁面,我們點擊 tab-2,tab-2 就被激活了。這個時候,我們刷新頁面或者是將此頁面分享給別人,打開頁面以后又回到了 tab-1,這樣就會出現同樣的 url 看到的界面卻是不一樣的。那么如何才能使你的界面狀態是可分享?

1. 使用哈希來保存當前頁面狀態信息
通過 index 來記錄用戶點擊的是第幾個 tab, 使用 hash 來記錄這個狀態。

  // HTML和CSS不變
  // js
  let index = location.hash || '#0' //2
  index = index.substring(1)  //3
  $('x-tab > .nav > li').eq(index).addClass('active').siblings()
    .removeClass('active');
  $('x-tab > .content > li').eq(index).addClass('active').siblings()
    .removeClass('active');    

  $('x-tab').on('click', '.nav > li', (e)=>{
    let $li = $(e.currentTarget);
    $li.addClass('active').siblings().removeClass('active');
    let index = $li.index(); //點的是第幾個tab
    location.hash = index // 1
    $li.closest('x-tab').find('.content > li').eq(index).addClass('active')
      .siblings().removeClass('active')
  })

通過三個步驟:

  1. 設置 hash
  2. 讀取 hash
  3. 分享 hash

這樣呢我們的界面狀態就可以通過錨點來記錄了,將鏈接復制到另一個窗口上打開依然是原來的狀態,此時就簡單的實現了,刷新頁面當前狀態不改變,同時當前狀態可分享給別人。

2. 使用 a 標簽 和監聽哈希變更事件
上面的例子中,其實我們點擊事件保存的就是形如后綴為 #0 和 #1 這樣的 url。有沒有另外一種可能,既然我們是通過錨點來切換 tab 的話,那能不能用 a 標簽來做呢?

這樣我們點擊 tab 的時候更改變化的是 url,就不去監聽 click 事件了,我們監聽什么事件呢?是哈希變更事件(hashchange),就是如果 a 標簽點擊之后哈希是1,就把第一個添加上一個紅色背景。代碼如下:

  // HTML
  <x-tab>
    <ol class="nav">
      <li><a href="#0"> tab 1 </a></li>
      <li><a href="#1"> tab 2 </a></li>
    </ol>
    <ol class="content">
      <li>content 1</li>
      <li>content 2</li>
    </ol>
  </x-tab>

  // js
  selectTab()   
  window.onhashchange = (e)=>{
    selectTab()
  }

  function selectTab(){
    let index = location.hash || '#0'
    index = index.substring(1)
    $('x-tab > .nav > li').eq(index).addClass('active').siblings()
      .removeClass('active');
    $('x-tab > .content > li').eq(index).addClass('active').siblings()
      .removeClass('active');  
  }

這種方法代碼也精簡了很多,其實就 3 行代碼,首先選擇下 tab,當哈希變化的時候,再選擇一下 tab 。

但是這個哈希還有很大的問題,就是如果還有一個回到頂部的鏈接。原本我們已經選中了 tab-2 ,但是點擊了回到頂部以后原來的狀態被覆蓋了,因此在刷新頁面或其他窗口打開的時候就沒有了原來的狀態。

3. 使用路徑來代替哈希
在上面的例子中,如果在 a 標簽中使用錨點表示某個狀態,容易被其他的錨點所覆蓋。那么我們直接使用路徑來代替哈希,當點擊 tab1 就跳轉到 <a href="./tab1">,當點擊 tab2 就跳轉到 <a href="./tab2">。

但是這個請求不可能成功,因為后臺根本就沒有響應 './tab1'和'./tab2'這個路徑。當點擊 tab1 的時候它會跳頁面,就會去請求 tab1 這個頁面,返回的是 404。

實際上我們的目的不是跳轉頁面只是想改變 url,沒關系,我么可以阻止 a 標簽的默認事件,不要它跳轉(e.preventDefault())。

  // HTML
  <x-tab>
    <ol class="nav">
      <li><a href="./tab1"> tab 1 </a></li>
      <li><a href="./tab2"> tab 2 </a></li>
    </ol>
    <ol class="content">
      <li>content 1</li>
      <li>content 2</li>
    </ol>
  </x-tab>

  // js 
  selectTab()   
  $('x-tab').on('click', '.nav > li > a', (e)=>{
    e.preventDefault();
    let a = e.currentTarget;
    let path = a.getAttribute('href');
    window.history.pushState({], xxx, path);
    selectTab();
  })

  function selectTab(){
    let index = location.pathname.substring(1) || 'tab1';
    index = index.substring(3);
    if(index === 1){
      $('x-tab > .nav > li').eq(0).addClass('active').siblings()
        .removeClass('active');
      $('x-tab > .content > li').eq(0).addClass('active').siblings()
        .removeClass('active');  
    }else if(index === 2){
      $('x-tab > .nav > li').eq(1).addClass('active').siblings()
        .removeClass('active');
      $('x-tab > .content > li').eq(1).addClass('active').siblings()
        .removeClass('active'); 
    }
  }

這樣我們點擊 tab1 或者 tab2 的時候,就只是改了 url,沒有跳轉頁面這就叫做巧用 History API無刷新更改地址欄。

現在的問題是此時的頁面狀態是不可分享的,返回 404,后臺沒有這個路徑的路由信息。因為所有的 url 都是先給服務器過一遍,然后再給 js 的。

這個時候我們可以自己寫一個后端路由來模擬實現刷新頁面后不跳轉頁面,當路徑為 / 或者/tab1 或者 /tab2 的時候都是返回同一個頁面。

  if(path === '/' || path === '/tab1' || path === '/tab2'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    let string = fs.readFileSync('./index.html','utf8')
    response.write(string)
    response.end()
  }else{
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write('嗚嗚嗚')
    response.end()
  }

這樣就不會去通知服務器,js 做的假的頁面跳轉,同時把頁面更新到對應的狀態。

現在我們應該可以知道了

1. 路由就是給我一個路徑,我給你返回一個響應

2. 前端路由就是前端頁面做這個事情,前端做路由

3. 后端路由呢就是后端做路由

以上的前端路由,也就是 Vue-Router 中 <router-link></router-link>的實現原理。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容