前端路由(history+hash)

在傳統網站開發中,咱們通常使用好比asp、php、jsp等技術進行開發,開發完成後統一部署在服務器上,咱們訪問時,會在瀏覽器中發送帶有'.asp','.php','.jsp'等後綴路徑的url請求,服務器會根據對應的路由映射表,找到咱們請求的頁面並渲染成HTML,而後把HTML頁面直接返回給瀏覽器展現,這就是所謂的服務器端渲染SSR(Server Side Render)。javascript

然而隨着前端頁面複雜性的提升以及前端技術的興起(尤爲是Ajax技術的興起),行業內愈來愈推崇先後端分離的開發模式。使服務器端不在關注HTML頁面的渲染,而是隻專一於邏輯的開發,經過Api提供數據;前端只專一於UI的開發,把從服務器請求的數據生成DOM插入到頁面中去。從服務器請求數據,而後由客戶端經過前端技術生成展現頁面的方式就是客戶端渲染CSR(Client Side Render)。php

客戶端渲染使先後端進行了分離,各自只關注屬於本身的部分,而且使用戶體驗也獲得了提高,用戶交互不用每次都刷新頁面。基於這些優勢,單頁應用(SPA(Single Page Web Application))的開發模型備受青睞。能夠作到動態重寫當前頁面來與用戶交互,而不須要從新加載整個頁面。然而要實現單頁應用,作到交互和跳轉都不須要刷新的體驗,須要解決一個重要問題,就是路由問題。因此就有了前端路由,其實前端路由是相對於服務器端路由的稱謂,由前端控制維護url和UI之間的映射關係,url更改後引發ui更新,而無需刷新頁面。html

下面就讓咱們經過兩種方式實現前端路由:前端

實現前端路由的總體思路:
首先維護一張包含path和對應的頁面內容的路由映射表,當監聽到路由發生變化後,從路由映射表中篩選出對應的路由信息,並把路由信息中對應的內容頁面渲染添加到html頁面展現。開始以前先了解下兩種方式的基本知識。java

1.window.history

Window.history是一個只讀屬性,用來獲取包含操做瀏覽器會話歷史History 對象。
主要方法:
back()
前往上一頁, 用戶可點擊瀏覽器左上角的返回按鈕模擬此方法. 等價於 history.go(-1)
forward()
在瀏覽器歷史記錄裏前往下一頁,用戶可點擊瀏覽器左上角的前進按鈕模擬此方法. 等價於 history.go(1)
go()
經過當前頁面的相對位置從瀏覽器歷史記錄( 會話記錄 )加載頁面
pushState()
按指定的名稱和URL(若是提供該參數)將數據push進會話歷史棧,數據被DOM進行不透明處理;你能夠指定任何能夠被序列化的javascript對象。
replaceState()
按指定的數據,名稱和URL(若是提供該參數),更新歷史棧上最新的入口。這個數據被DOM 進行了不透明處理。你能夠指定任何能夠被序列化的javascript對象。後端

2.location.hash

hash 屬性是一個可讀可寫的字符串,該字符串是 URL 的錨部分(從 # 號開始的部分)。瀏覽器

實現代碼以下:服務器

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>window.history路由</title>
</head>

<body>
  <div>
    <div id="routerLink">
      <div>
        <button onclick="historyChange('home')">首頁(history)/button>
          <button onclick="historyChange('about')">關於(history)</button>
      </div>
      <div>
        <button onclick="hashChange('home')">首頁(hash)</button>
        <button onclick="hashChange('about')">關於(hash)</button>
      </div>
    </div>
    <div>
      <div id="routerView">

      </div>
    </div>
  </div>
  <!-- 2.建立子視圖模板 -->
  <template id="home">
    <div>hello,我是首頁</div>
  </template>
  <template id="about">
    <div>hello,我是關於</div>
  </template>
  <script>
    //1.首先建立路由表
    const routerTable = [
      {
        path: 'home',
        component: '#home'
      },
      {
        path: 'about',
        component: '#about'
      }
    ]

    //*********** 方式一:window.history **************
    //3.(window.history)監聽路由更改,根據新路由path加載對應的內容
    function historyChange(path) {
      render({ path: path })
    }
    //添加popstate狀態監聽
    window.addEventListener('popstate', function (e) {
      if (e) {
        render({ path: e.state, isPush: false })
      }
    })

    //************** 方式二:location.hash ***************
    function hashChange(path) {
      render({ path: path, mode: 'hash' })
    }
    //添加hashchange監聽
    window.addEventListener('hashchange', function () {
      let path = location.hash
      //path移除開始的#
      render({ path: path.substring(1, path.length - 2), mode: 'hash' })
    })

    //**************公共方法*******************
    //渲染方法
    function render(data) {
      //默認值,mode默認爲history,isPush=true,isReplace=false,path=home
      data = Object.assign({ mode: 'history', isPush: true, isReplace: false, path: 'home' }, data)
      if (data.path) {
        //查詢路由信息
        const route = routerTable.find(p => p.path == data.path);
        if (route) {
          if (data.mode == 'history') {
            if (data.isPush) {
              //更改url---後退、前進不更改
              if (data.isReplace) {
                window.history.replaceState(data.path, '', data.path)
              } else {
                window.history.pushState(data.path, '', data.path)
              }
            }
          } else if (data.mode == 'hash') {
            location.hash = data.path
          }
          //更新html
          document.querySelector("#routerView").innerHTML = document.querySelector(route.component).innerHTML
        }
      }
    }
  </script>
</body>
</html>

 

PS須要用http的方式運行頁面,要否則pushState是沒法使用的,會報:cannot be created in a document with origin 'null'的錯誤。
不過若是你電腦上已經安裝了vscode,能夠下載Live Server插件,來運行html文件。前後端分離

CSR-jsp

相關文章
相關標籤/搜索