為什么要有 hash 和 history
對(duì)于 Vue 這類漸進(jìn)式前端開發(fā)框架,為了構(gòu)建 SPA(單頁面應(yīng)用),需要引入前端路由系統(tǒng),這也就是 Vue-Router 存在的意義。前端路由的核心,就在于 —— 改變視圖的同時(shí)不會(huì)向后端發(fā)出請(qǐng)求。
為了達(dá)到這一目的,瀏覽器當(dāng)前提供了以下兩種支持:
1.hash —— 即地址欄 URL 中的 # 符號(hào)(此 hash 不是密碼學(xué)里的散列運(yùn)算)。
比如這個(gè) URL:http://www.abc.com/#/hello,hash 的值為 #/hello。它的特點(diǎn)在于:hash 雖然出現(xiàn)在 URL 中,“#”后面的內(nèi)容不會(huì)被包括在 HTTP 請(qǐng)求中,對(duì)后端完全沒有影響,因此改變 hash 不會(huì)重新加載頁面。
2.history —— 利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。(需要特定瀏覽器支持)
這兩個(gè)方法應(yīng)用于瀏覽器的歷史記錄棧,在當(dāng)前已有的 back、forward、go 的基礎(chǔ)之上,它們提供了對(duì)歷史記錄進(jìn)行修改的功能。只是當(dāng)它們執(zhí)行修改時(shí),雖然改變了當(dāng)前的 URL,但瀏覽器不會(huì)立即向后端發(fā)送請(qǐng)求。
因此可以說,hash 模式和 history 模式都屬于瀏覽器自身的特性,Vue-Router 只是利用了這兩個(gè)特性(通過調(diào)用瀏覽器提供的接口)來實(shí)現(xiàn)前端路由。
vue-router 的 history 模式是個(gè)提高顏值的好東西,沒有了 hash 的路由看起來清爽許多。
開發(fā)的時(shí)候,如果我們使用 devServer 來啟動(dòng)服務(wù),由于一般不共用端口,我們一般不存在非根目錄的問題。
而刷新后 404 的問題可以借助 historyApiFallback 來解決。
但當(dāng)我們項(xiàng)目對(duì)外開放時(shí),往往無法在域名根目錄下提供服務(wù),這個(gè)時(shí)候資源的訪問路徑與開發(fā)時(shí)的根目錄就有了區(qū)別。
首先,我們通過 webpack 來配置一下項(xiàng)目中所有資源的基礎(chǔ)路徑,讓這份代碼在開發(fā)和生產(chǎn)環(huán)境中都可以正確找到資源。
// config/index.jsmodule.exports = { dev: { ... // 開發(fā)環(huán)境根目錄 - 服務(wù)根目錄 - 絕對(duì)路徑 assetsPublicPath: '/' ... }, build: { ... // 生產(chǎn)環(huán)境根目錄 - 服務(wù)器訪問路徑 - 絕對(duì)路徑 assetsPublicPath: '/test/project1/' ... }} // build/webpack.common.conf.jsconst config = require('../config')module.exports = { output: { publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath }}// build/webpack.dev.conf.jsconst common = require('./webpack.common')module.exports = merge(common, { devServer: { historyApiFallback: true }}然后在提供服務(wù)的服務(wù)器配置中做如下配置(以 nginx 為例):
location /test/project1 { alias .../project1; // 項(xiàng)目的真實(shí)路徑 index index.html; try_files $uri $uri/ /test/project1/index.html;}
新聞熱點(diǎn)
疑難解答
圖片精選