記錄--啊?Vue是有三種路由模式的?

来源:https://www.cnblogs.com/smileZAZ/archive/2023/11/11/17826204.html
-Advertisement-
Play Games

這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 眾所周知,vue路由模式常見的有 history 和 hash 模式,但其實還有一種方式-abstract模式(瞭解一哈~) 別急,本文我們將重點逐步瞭解: 路由 + 幾種路由模式 + 使用場景 + 思考 + freestyle 路由概念 ...


這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助

眾所周知,vue路由模式常見的有 historyhash 模式,但其實還有一種方式-abstract模式(瞭解一哈~)

別急,本文我們將重點逐步瞭解: 路由 + 幾種路由模式 + 使用場景 + 思考 + freestyle


路由概念

路由的本質就是一種對應關係,根據不同的URL請求,返回對應不同的資源。那麼url地址和真實的資源之間就有一種對應的關係,就是路由。


路由模式由來

對於 Vue 這類漸進式前端開發框架,為了構建 SPA(單頁面應用),需要引入前端路由系統,這也就是 Vue-Router 存在的意義。而前端路由的核心,就在於 —— 改變視圖的同時不會向後端發出請求

為了達到這一目的,就產生了我們的 —— 路由模式


三種路由模式詳解


hash模式

示例: www.ikun.com/#/kun,hash 的值為 #/kun。

概述:

地址欄 URL 中有 # 符號,後面就是 hash 值的變化(此 hash 不是密碼學里的散列運算)。特點是:hash 雖然出現在 URL 中,但不會被包括在 HTTP 請求中,對後端沒有影響,改變後面的 hash 值,它不會向伺服器發出請求,因此也就不會 刷新頁面/重新載入頁面

每次 hash 值發生改變的時候,會觸發 hashchange 事件。因此我們可以通過監聽該事件,來知道 hash 值發生了哪些變化。

window.addEventListener('hashchange', ()=>{
    // 通過 location.hash 獲取到最新的 hash 值
    console.log(location.hash);
});
使用:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>hash路由</title>
</head>
<body>
​
  <ul>
    <!-- 通過標簽導航  聲明式導航 -->
    <!-- location.href='#/home' js方式進行導航切換 編程式導航 -->
    <li><a href="#/home">首頁</a></li>
    <li><a href="#/about">關於</a></li>
  </ul>
​
  <div id="routerView"></div>
​
  <script>
    const routerRender = () => {
      // 每次都置空hash
      let html = ''
      // 根據地址欄hash值的不同返回對應的資源
      try {
        // 如果hash值為空就給一個home
        let hash = location.hash || '#/home'
        html = component[hash.slice(2)]()
      } catch (error) {
        html = `<div>404</div>`
      }
      // 渲染到頁面上
      document.getElementById('routerView').innerHTML = html
    }
​
    const component = {
      home() {
        return `<div>home頁面</div>`
      },
      about() {
        return '<div>關於頁面</div>'
      }
    }
​
    window.onload = function () {
      routerRender()
    }
​
    // 事件,監聽地址欄中的hash值變化,實現回退
    window.addEventListener('hashchange', routerRender)
      
  </script>
</body>
</html>

優缺點:

優點:hash模式相容性、安全性很強,刷新瀏覽器,頁面還會存在

缺點:地址欄不優雅,有#存在,不利於seo,記憶困難

註意:

hash 模式既可以通過聲明式導航,也可以通過編程式導航,上面的案例展示的是聲明式導航。而下麵將要講到的 history 模式只能通過編程式導航實現,因為 history 是 js 對象。


history模式

示例: www.ikun.com/kun,地址欄中沒有#,路由地址跟正常的url一樣

概述:

history —— 利用了 HTML5 History API 為瀏覽器的全局 history 對象增加的 pushState()replaceState() 方法,可以對瀏覽器歷史記錄棧進行修改。(新增特性,所以瀏覽器需考慮IE9以及以下的版本帶來的問題)。當地址欄的history狀態發生變化時 切換了router-view渲染的組件 來"欺騙"用戶 到達切換新網頁的效果,需要後端配合

History 還包括back、forward、go三個方法,對應瀏覽器的前進,後退,跳轉操作。就是瀏覽器左上角的前進、後退等按鈕進行的操作。

history.go(-2);//後退兩次
history.go(2);//前進兩次
history.back(); //後退
hsitory.forward(); //前進

只要歷史棧有信息發生改變的話,window對象中提供的 popstate 事件就會監聽到歷史棧的改變,就會觸發該事件。

history.pushState({},title,url); // 向歷史記錄中追加一條記錄
history.replaceState({},title,url); // 替換當前頁在歷史記錄中的信息。
​
window.addEventListener('popstate', function(e) {
  console.log(e)
})

使用:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>history模式</title>
</head>
​
<body>
  <ul>
    <li><a href="/home">首頁</a></li>
    <li><a href="/about">關於</a></li>
  </ul>
​
  <div id="routerView"></div>
​
  <script>
    const component = {
      home() {
        return `<div>home頁面</div>`
      },
      about() {
        return '<div>關於頁面</div>'
      }
    }
​
    const routerRender = pathname => {
      let html = ''
      try {
        html = component[pathname]()
      } catch (error) {
        html = `<div>404</div>`
      }
      document.getElementById('routerView').innerHTML = html
    }
​
    // history模式,它的路由導航,只能通過js來完成 , history它是js對象
    // 給鏈接添加點擊事件
    document.querySelectorAll('a').forEach(node => {
      node.addEventListener('click', function (evt) {
        // 阻止a標簽的預設跳轉行為
        evt.preventDefault()
        // 跳轉到指定的地址,能回退
        // history.pushState
        // 跳轉到指定持址,不能回退
        // history.replaceState
        history.pushState({}, null, this.href)
        // 渲染
        routerRender(this.href.match(//(\w+)$/)[1])
      })
    })
​
    // 在網頁載入完畢後立刻執行的操作,即當 HTML 文檔載入完畢後,立刻渲染 home 中的標簽
    window.onload = () => {
      routerRender('home')
    }
​
    // 回退
    window.addEventListener('popstate', function () {
      routerRender(location.pathname.slice(1))
    })
​
  </script>
</body>
</html>

優缺點:

缺點:history模式,相容性較差,刷新頁面,頁面會404,需要伺服器端配置支持

優點:地址欄更優雅,方便記憶,有利於有seo


刷新頁面出現404原因以及解決:

原因:

因為vue項目中路由hash模式改為了history模式,由於hash模式時url帶的#號後面是哈希值不會作為url的一部分發送給伺服器,而history模式下當刷新頁面之後瀏覽器會直接去請求伺服器,而伺服器沒有這個路由,於是就出現404

因為我們的應用是單頁客戶端應用,當使用 history 模式時,URL 就像正常的 url,可以直接訪問www.ikun.com/kun/love,但是因為 vue-router 設置的路徑不是真實存在的路徑,所以刷新就會返回404錯誤

解決方法(後端配合,這裡講的是nginx配置):

在服務端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態資源,則應該返回同一個 index.html 頁面,這個頁面就是你 app 依賴的頁面。也就是在服務端修改404錯誤頁面的配置路徑,讓其指向到index.html

方法一:

    location /{
        root   /data/nginx/html;
        index  index.html index.htm;
        if (!-e $request_filename) {
            rewrite ^/(.*) /index.html last;
            break;
        }
    }

方法二: (vue.js官方教程里提到的https://router.vuejs.org/zh-cn/essentials/history-mode.html)

  server {
        listen       8888;#預設埠是80,如果埠沒被占用可以不用修改
        server_name  localhost;
        root        E:/vue/my_project/dist;#vue項目的打包後的dist
        location / {
            try_files $uri $uri/ @router;#需要指向下麵的@router否則會出現vue的路由在nginx中刷新出現404
            index  index.html index.htm;
        }
        #對應上面的@router,主要原因是路由的路徑資源並不是一個真實的路徑,所以無法找到具體的文件
        #因此需要rewrite到index.html中,然後交給路由在處理請求資源
        location @router {
            rewrite ^.*$ /index.html last;
        }
        #.......其他部分省略
  }

abstract模式

abstract模式----適用於所有JavaScript環境,例如伺服器端使用Node.js。如果沒有瀏覽器API,路由器將自動被強制進入此模式。

abstract 是一種與瀏覽器分離的路由模式,本身是用來在不支持瀏覽器API的環境中,充當fallback,而不論是hash還是history模式都會對瀏覽器上的url產生作用。

利用abstract這種與瀏覽器分離的路由模式,我們可以在已存在的路由頁面中內嵌其他的路由頁面,而保持在瀏覽器當中依舊顯示當前頁面的路由path。


使用場景


history --- 顏值性(強迫症患者推薦,更友好的URL格式、SEO支持)

一般場景下,hash 和 history 都可以,除非你更在意顏值,# 符號夾雜在 URL 里看起來確實有些不太美麗。我們可以用路由的 history 模式,充分利用 history.pushState API 來完成URL 跳轉而無須重新載入頁面。如果需要更好的SEO支持,並且願意進行伺服器端配置,history 模式是很好的選擇

調用 history.pushState() 相比於直接修改 hash,還存在以下優勢

1、pushState() 設置的新 URL 可以是與當前 URL 同源的任意 URL;而 hash 只可修改 #後面的部分,因此只能設置與當前 URL 同文檔的 URL;

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

3、pushState() 通過 stateObject 參數可以添加任意類型的數據到記錄中;而 hash 只可添加短字元串;

4、pushState() 可額外設置 title 屬性供後續使用。

hash ---- 安全相容,不需要後端協助

SPA 雖然在瀏覽器里游刃有餘,但真要通過 URL 向後端發起 HTTP 請求時,兩者的差異就來了。尤其在用戶手動輸入 URL 後回車,或者刷新(重啟)瀏覽器的時候

hash 模式下,僅 hash 符號之前的內容會被包含在請求中,如 www.ikun.com ,因此對於後端來說,即使沒有做到對路由的全覆蓋,也不會返回 404 錯誤

abstract模式 ---- 特殊場景

abstract模式----適用於所有JavaScript環境(瀏覽器端和服務端),例如伺服器端使用Node.js。

像上文說的,可以利用abstract這種與瀏覽器分離的路由模式,在已存在的路由頁面中內嵌其他的路由頁面,而保持在瀏覽器當中依舊顯示當前頁面的路由path。


小結


選擇使用 hash 模式還是 history 模式,主要取決於你的具體需求和項目要求。如果你的應用不需要考慮SEO,並且不涉及伺服器端的重定向和處理,Hash模式是一種簡單且易於使用的選擇。如果你需要更友好的URL格式、更好的SEO支持,並且願意進行伺服器端配置,那麼history 模式是更好的選擇。

結合自身例子,對於一般形式的 Web 開發場景,個人比較習慣用用 history 模式,只需在後端(Apache 或 Nginx)進行簡單的路由配置,同時搭配前端路由的 404 頁面支持。

本文轉載於:

https://juejin.cn/post/7297035708429484066

如果對您有所幫助,歡迎您點個關註,我會定時更新技術文檔,大家一起討論學習,一起進步。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • UTL_MATCH介紹: Oracle的UTL_MATCH包是一個提供字元串匹配和相似度計算功能的工具包。它包含了一系列函數,用於執行字元串比較、相似度計算和模式匹配等操作。 UTL_MATCH包中的函數可以用於以下任務: 字元串相似度計算:UTL_MATCH提供了多個函數來計算字元串之間的相似度, ...
  • 1、編輯距離 編輯距離:是衡量兩個字元串之間差異的度量,它表示將一個字元串轉換為另一個字元串所需的最少編輯操作次數(插入、刪除、替換)。 2、相似度 計算方法可以有多種,其中一種常見的方法是將編輯距離歸一化為0到1之間的範圍(歸一化編輯距離(Normalized Edit Distance)),將編 ...
  • 之前講了「如何配置普通的 RSA2 密鑰」,今天來捋一下如何配置證書~ 依照慣例先放一下官方文檔:[如何生成及配置公鑰證書],小伙伴們也可以直接按照文檔來~ 前期準備:證書的適用範圍 目前支付寶的所有產品都支持證書密鑰去進行調用。 其中「單筆轉賬」和「現金紅包」 只能使用 證書 進行介面調用。 詳情 ...
  • SciPy的linalg模塊是SciPy庫中的一個子模塊,它提供了許多用於線性代數運算的函數和工具,如矩陣求逆、特征值、行列式、線性方程組求解等。 相比於NumPy的linalg模塊,SciPy的linalg模塊包含更多的高級功能,並且在處理一些特定的數值計算問題時,可能會表現出更好的性能。 1. ...
  • 深入理解CAS 什麼是CAS 為什麼要學CAS:大廠你必須深入研究底層!有所突破! java層面的cas >compareAndSet compareAndSet(int expectedValue, int newValue) 期望並更新,達到期望值就更新、否則就不更新! package org. ...
  • 思想 DAO(Data Access Object)數據訪問對象,是我們在做結構化資料庫訪問的時候傳輸的對象,通過這個對象我們可以與資料庫中的表建立映射關係 DTO(Data Transfer Object)是我們在與前端進行數據交換時傳遞的對象 為什麼需要設置這這兩種對象呢? 為了數據安全 如果我 ...
  • 前言: 繼上篇:Taurus .Net Core 微服務開源框架:Admin 插件【4-3】 - 配置管理 - Mvc【Plugin-MicroService 微服務】 本篇繼續介紹下一個內容: 系統配置節點:Mvc - Plugin - CORS 跨域界面: 界面如下: 跨域功能相關配置說明如下: ...
  • 前言 由於業務需要,需要多台雲伺服器,但是公有雲的帶寬價格不菲,所以不可能給所有的雲伺服器都配上公網IP,一方面是成本的問題,另一方面也是公網安全的問題。 所以通過其它的方式使用無公網的雲伺服器來來實現對外資源的訪問。 一、操作步驟 至少需要有一臺具有公網IP的雲伺服器! 1、開啟ECS的路由轉發功 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...