一区二区日本_久久久久久久国产精品_无码国模国产在线观看_久久99深爱久久99精品_亚洲一区二区三区四区五区午夜_日本在线观看一区二区

hash和history路由模式區別示例解析

目錄 單頁應用 hash模式 hashChange() history模式 hash模式和history模式的區別 單頁應用 目前單頁應用(SPA)越來越成為前端主流,單頁應用一大特點就是使用前端路由,由前端來直接控制路
目錄
  • 單頁應用
  • hash模式
    • hashChange()
  • history模式
    • hash模式和history模式的區別

      單頁應用

      目前單頁應用(SPA)越來越成為前端主流,單頁應用一大特點就是使用前端路由,由前端來直接控制路由跳轉邏輯,而不再由后端人員控制,這給了前端更多的自由。

      目前前端路由主要有兩種實現方式:hash模式和history模式,下面分別詳細說明。

      hash模式

      這個我們應該不陌生,比如在用超鏈接制作錨點跳轉的時候,就會發現,url后面跟了"#id",hash值就是url中從"#"號開始到結束的部分

      hash值變化瀏覽器不會重新發起請求,但是會觸發window.hashChange事件,假如我們在hashChange事件中獲取當前的hash值,并根據hash值來修改頁面內容,則達到了前端路由的目的。

      html:菜單中href設置為hash形式,id為app中放置頁面內容

      <ul id="menu">
          <li>
              <a  rel="external nofollow" >首頁</a>
          </li>
          <li>
              <a  rel="external nofollow" >資訊</a>
          </li>
          <li>
              <a  rel="external nofollow" >個人中心</a>
          </li>
      </ul>

      <div id="app"></div>

      js:在window.onhashchange中獲取hash值,根據不同的值,修改app中不同的內容,起到了路由的效果

      function hashChange(e){
          // console.log(location.hash)
          // console.log(location.href)
          //
          // console.log(e.newURL)
          // console.log(e.oldURL)
          let app = document.getElementById('app')
          switch (location.hash) {
              case '#index':
                  app.innerHTML = '<h1>這是首頁內容</h1>'
                  break
              case '#news':
                  app.innerHTML = '<h1>這是新聞內容</h1>'
                  break
              case '#user':
                  app.innerHTML = '<h1>這是個人中心內容</h1>'
                  break
              default:
                  app.innerHTML = '<h1>404</h1>'
          }
      }

      window.onhashchange = hashChange

      hashChange()

      上面這個實現方式比較簡陋,我們可以再封裝一下

      class Router {
      constructor(){
          this.routers = []  //存放我們的路由配置
      }
      add(route,callback){
          this.routers.push({
              path:route,
              render:callback
          })
      }
      listen(callback){
          window.onhashchange = this.hashChange(callback)
          this.hashChange(callback)()  //首次進入頁面的時候沒有觸發hashchange,必須要就單獨調用一下
      }
      hashChange(callback){
          let self = this
          return function () {
              let hash = location.hash
              console.log(hash)
              for(let i=0;i<self.routers.length;i++){
                  let route = self.routers[i]
                  if(hash===route.path){
                      callback(route.render())
                      return
                  }
              }
          }
      }
      }
      let router = new Router()
      router.add('#index',()=>{
      return '<h1>這是首頁內容</h1>'
      })
      router.add('#news',()=>{
      return ?'<h1>這是新聞內容</h1>'
      })
      router.add('#user',()=>{
      return ?'<h1>這是個人中心內容</h1>'
      })
      router.listen((renderHtml)=>{
      let app = document.getElementById('app')
      app.innerHTML = renderHtml
      })

      實現一個Router類,通過add方法添加路由配置,第一個參數為路由路徑,第二個參數為render函數,返回要插入頁面的html;通過listen方法,監聽hash變化,并將每個路由返回的html,插入到app中。

      這樣我們就實現了一個簡單的hash路由。

      history模式

      hash模式看起來是比較丑的,都帶個"#"號,我們也可以采取history模式,history就是我們平時看到的正常的連接形式

      https://www.baidu.com#plan/index?//hash模式路由
      https://www.baidu.com/plan/index?//history模式路由

      history模式基于window.history對象的方法

      在HTML4中,已經支持window.history對象來控制頁面歷史記錄跳轉,常用的方法包括:

      history.forward(); //在歷史記錄中前進一步

      history.back(); //在歷史記錄中后退一步

      history.go(n): //在歷史記錄中跳轉n步驟,n=0為刷新本頁,n=-1為后退一頁。

      在HTML5中,window.history對象得到了擴展,新增的API包括:

      history.pushState(data,title);//向歷史記錄中追加一條記錄

      history.replaceState(data,title);//替換當前頁在歷史記錄中的信息。

      history.state;//是一個屬性,可以得到當前頁的state信息。

      window.onpopstate;//是一個事件,在點擊瀏覽器后退按鈕或js調用forward()、back()、go()時觸發。監聽函數中可傳入一個event對象,event.state即為通過pushState()或replaceState()方法傳入的data參數

      history模式原理可以這樣理解,首先我們要改造我們的超鏈接,給每個超鏈接增加onclick方法,阻止默認的超鏈接跳轉,改用history.pushState或history.replaceState來更改瀏覽器中的url,并修改頁面內容。由于通過history的api調整,并不會向后端發起請求,所以也就達到了前端路由的目的。

      如果用戶使用瀏覽器的前進后退按鈕,則會觸發window.onpopstate事件,監聽頁面根據路由地址修改頁面內容。

      也不一定非要用超鏈接,任意元素作為菜單都行,只要在點擊事件中通過history進行調整即可。

      html:

      <ul id="menu">
      <li>
          <a  rel="external nofollow" >首頁</a>
      </li>
      <li>
          <a  rel="external nofollow" >資訊</a>
      </li>
      <li>
          <a  rel="external nofollow" >個人中心</a>
      </li>
      </ul>
      <div id="app"></div>

      js:

      //改造超鏈接,阻止默認跳轉,默認的跳轉是會刷新頁面的
      document.querySelector('#menu').addEventListener('click',function (e) {
      if(e.target.nodeName ==='A'){
          e.preventDefault()
          let path = e.target.getAttribute('href')  //獲取超鏈接的href,改為pushState跳轉,不刷新頁面
          window.history.pushState({},'',path)  //修改瀏覽器中顯示的url地址
          render(path)  //根據path,更改頁面內容
      }
      })
      function render(path) {
      let app = document.getElementById('app')
      switch (path) {
          case '/index':
              app.innerHTML = '<h1>這是首頁內容</h1>'
              break
          case '/news':
              app.innerHTML = '<h1>這是新聞內容</h1>'
              break
          case '/user':
              app.innerHTML = '<h1>這是個人中心內容</h1>'
              break
          default:
              app.innerHTML = '<h1>404</h1>'
      }
      }
      //監聽瀏覽器前進后退事件,并根據當前路徑渲染頁面
      window.onpopstate = function (e) {
          render(location.pathname)
      }
      //第一次進入頁面顯示首頁
      render('/index')
      上面這個寫法太low,我們可以用類封裝一下,通過add方法添加路由,通過pushState進行跳轉,初始化時更改所以超鏈接的跳轉方式
      class Router {
          constructor(){
          this.routers = []
          this.renderCallback = null
      }
      add(route,callback){
          this.routers.push({
              path:route,
              render:callback
          })
      }
      pushState(path,data={}){
          window.history.pushState(data,'',path)
          this.renderHtml(path)
      }
      listen(callback){
          this.renderCallback = callback
          this.changeA()
          window.onpopstate = ()=>this.renderHtml(this.getCurrentPath())
          this.renderHtml(this.getCurrentPath())
      }
      changeA(){
          document.addEventListener('click', (e)=> {
              if(e.target.nodeName==='A'){
                  e.preventDefault()
                  let path = e.target.getAttribute('href')
                  this.pushState(path)
              }
          })
      }
      getCurrentPath(){
          return location.pathname
      }
      renderHtml(path){
          for(let i=0;i<this.routers.length;i++){
              let route = this.routers[i]
              if(path===route.path){
                  this.renderCallback(route.render())
                  return
              }
          }
      }
      }
      let router = new Router()
      router.add('/index',()=>{
      return '<h1>這是首頁內容</h1>'
      })
      router.add('/news',()=>{
      return  '<h1>這是新聞內容</h1>'
      })
      router.add('/user',()=>{
      return  '<h1>這是個人中心內容</h1>'
      })
      router.listen((renderHtml)=>{
      let app = document.getElementById('app')
      app.innerHTML = renderHtml
      })

      當然,上面這個實現只是一個非常初級的demo,并不能用于真正的開發場景,只是加深對前端路由的理解。

      hash模式和history模式的區別

      hash模式較丑,history模式較優雅

      pushState設置的新URL可以是與當前URL同源的任意URL;而hash只可修改#后面的部分,故只可設置與當前同文檔的URL

      pushState設置的新URL可以與當前URL一模一樣,這樣也會把記錄添加到棧中;而hash設置的新值必須與原來不一樣才會觸發記錄添加到棧中

      pushState通過stateObject可以添加任意類型的數據到記錄中;而hash只可添加短字符串

      pushState可額外設置title屬性供后續使用

      hash兼容IE8以上,history兼容IE10以上

      history模式需要后端配合將所有訪問都指向index.html,否則用戶刷新頁面,會導致404錯誤

      以上就是hash和history路由模式區別示例解析的詳細內容,更多關于hash history路由模式區別的資料請關注技圈網其它相關文章!

      聲明:所有內容來自互聯網搜索結果,不保證100%準確性,僅供參考。如若本站內容侵犯了原著者的合法權益,可聯系我們進行處理。
      發表評論
      更多 網友評論0 條評論)
      暫無評論

      返回頂部

      主站蜘蛛池模板: 国产精品亚洲精品 | 日韩精品一区二区三区在线播放 | 日韩视频二区 | 国产在线视频一区 | wwwxx在线观看| 日韩欧美在线播放 | 中文字幕一区二区三区在线观看 | 国产极品粉嫩美女呻吟在线看人 | 亚洲精品视频在线播放 | 国产欧美一区二区久久性色99 | www.啪啪.com| 国产精品美女久久久久久免费 | 超碰美女在线 | 成人在线免费观看 | 成人免费小视频 | 黄网站在线观看 | 亚洲精品一二区 | 91一区二区三区 | 久久久91精品国产一区二区三区 | 欧美日韩精品一区二区三区视频 | 99在线免费观看视频 | 国产aaaaav久久久一区二区 | 亚州精品成人 | 欧美在线一区二区三区 | 91国内外精品自在线播放 | 亚洲精品视频久久 | 日韩中文一区 | 国产精品99久久久久久动医院 | 日韩在线三级 | 国产成人精品久久 | 久久99国产精品 | 一久久久 | 免费电影av | 国产精品区二区三区日本 | 天堂av中文在线 | 成人免费三级电影 | 成年人免费在线视频 | 欧洲一区二区三区 | 国产精品久久久 | 欧美区日韩区 | 精品国产乱码久久久久久闺蜜 |