記錄--啊?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 微服務框架,幫助我們輕鬆構建和管理微服務應用。 本框架不僅支持 Consul 服務註 ...
  • 先看一下效果吧: 如果不會寫動畫或者懶得寫動畫,就直接交給Blend來做吧; 其實Blend操作起來很簡單,有點類似於在操作PS,我們只需要設置關鍵幀,滑鼠點來點去就可以了,Blend會自動幫我們生成我們想要的動畫效果. 第一步:要創建一個空的WPF項目 第二步:右鍵我們的項目,在最下方有一個,在B ...
  • Prism:框架介紹與安裝 什麼是Prism? Prism是一個用於在 WPF、Xamarin Form、Uno 平臺和 WinUI 中構建鬆散耦合、可維護和可測試的 XAML 應用程式框架 Github https://github.com/PrismLibrary/Prism NuGet htt ...
  • 在WPF中,屏幕上的所有內容,都是通過畫筆(Brush)畫上去的。如按鈕的背景色,邊框,文本框的前景和形狀填充。藉助畫筆,可以繪製頁面上的所有UI對象。不同畫筆具有不同類型的輸出( 如:某些畫筆使用純色繪製區域,其他畫筆使用漸變、圖案、圖像或繪圖)。 ...
  • 前言 嗨,大家好!推薦一個基於 .NET 8 的高併發微服務電商系統,涵蓋了商品、訂單、會員、服務、財務等50多種實用功能。 項目不僅使用了 .NET 8 的最新特性,還集成了AutoFac、DotLiquid、HangFire、Nlog、Jwt、LayUIAdmin、SqlSugar、MySQL、 ...
  • 本文主要介紹攝像頭(相機)如何採集數據,用於類似攝像頭本地顯示軟體,以及流媒體數據傳輸場景如傳屏、視訊會議等。 攝像頭採集有多種方案,如AForge.NET、WPFMediaKit、OpenCvSharp、EmguCv、DirectShow.NET、MediaCaptre(UWP),網上一些文章以及 ...
  • 前言 Seal-Report 是一款.NET 開源報表工具,擁有 1.4K Star。它提供了一個完整的框架,使用 C# 編寫,最新的版本採用的是 .NET 8.0 。 它能夠高效地從各種資料庫或 NoSQL 數據源生成日常報表,並支持執行複雜的報表任務。 其簡單易用的安裝過程和直觀的設計界面,我們 ...
  • 背景需求: 系統需要對接到XXX官方的API,但因此官方對接以及管理都十分嚴格。而本人部門的系統中包含諸多子系統,系統間為了穩定,程式間多數固定Token+特殊驗證進行調用,且後期還要提供給其他兄弟部門系統共同調用。 原則上:每套系統都必須單獨接入到官方,但官方的接入複雜,還要官方指定機構認證的證書 ...
  • 本文介紹下電腦設備關機的情況下如何通過網路喚醒設備,之前電源S狀態 電腦Power電源狀態- 唐宋元明清2188 - 博客園 (cnblogs.com) 有介紹過遠程喚醒設備,後面這倆天瞭解多了點所以單獨加個隨筆 設備關機的情況下,使用網路喚醒的前提條件: 1. 被喚醒設備需要支持這WakeOnL ...
  • 前言 大家好,推薦一個.NET 8.0 為核心,結合前端 Vue 框架,實現了前後端完全分離的設計理念。它不僅提供了強大的基礎功能支持,如許可權管理、代碼生成器等,還通過採用主流技術和最佳實踐,顯著降低了開發難度,加快了項目交付速度。 如果你需要一個高效的開發解決方案,本框架能幫助大家輕鬆應對挑戰,實 ...