摘要:原因在于將狀態對象保存在用戶的磁盤上,以便在用戶重啟瀏覽器時使用,我們規定了狀態對象在序列化表示后有的大小限制。新不必須為絕對路徑。新必須與當前同源,否則會拋出一個異常。注意絕對不會觸發事件,即使新的與舊的僅哈希不同也是如此。
Hash
hash 屬性是一個可讀可寫的字符串,該字符串是 URL 的錨部分(從 # 號開始的部分),在頁面中的hash有多種功能意義:
錨點url: http://www.example.com/index.html#jump dom: 或者瀏覽器讀取到hash之后自動滾動到該對應元素所在位置的可視區域內
不附加在請求上意味著它不管怎么變化都不會影響請求URL,即它只針對瀏覽器的.
瀏覽器: http://www.example.com/index.html#jump 服務器: http://www.example.com/index.html注意: 有種情況是你會在URL上帶#符號,但是你本意不是作為hash使用的,例如回調地址或者傳參之類,這時候瀏覽器只會當做hash處理,所以需要先轉碼.
// 未轉碼 瀏覽器: http://www.example.com/index.html?test=#123 服務器: http://www.example.com/index.html?test= // 轉碼 瀏覽器: http://www.example.com/index.html?test=%23123 服務器: http://www.example.com/index.html?test=%23123改變訪問歷史但不會觸發頁面刷新這個大家都知道,盡管它不會跳轉也不會刷新,但是你能通過點擊瀏覽器前進后退發現它也會被添加去訪問歷史記錄里.(低版本IE不考慮)
缺點搜索引擎不友好
難以追蹤用戶行為
思路當URL的片段標識符更改時,將觸發hashchange事件 (跟在#符號后面的URL部分,包括#符號),然后根據hash值做些路由跳轉處理的操作.具體參數可以訪問location查看
http://www.example.com/index.html#jump最基本的路由實現方法監聽事件根據location.hash判斷界面
Document 具體代碼可以查看hash_demo.html
HistoryDOM window 對象通過 history 對象提供了對瀏覽器的會話歷史的訪問。它暴露了很多有用的方法和屬性,允許你在用戶瀏覽歷史中向前和向后跳轉
向前和向后跳轉window.history.back(); window.history.forward();跳轉到 history 中指定的一個點你可以用 go() 方法載入到會話歷史中的某一特定頁面, 通過與當前頁面相對位置來標志 (當前頁面的相對位置標志為0).
window.history.go();添加歷史記錄中的條目不會立即加載頁面的情況下改變了當前URL地址,往歷史記錄添加一條條目,除非刷新頁面等操作
history.pushState(state, title , URL);狀態對象
state是一個JavaScript對象,popstate事件的state屬性包含該歷史記錄條目狀態對象的副本。
狀態對象可以是能被序列化的任何東西。原因在于Firefox將狀態對象保存在用戶的磁盤上,以便在用戶重啟瀏覽器時使用,我們規定了狀態對象在序列化表示后有640k的大小限制。如果你給 pushState() 方法傳了一個序列化后大于640k的狀態對象,該方法會拋出異常。如果你需要更大的空間,建議使用 sessionStorage 以及 localStorage.
標題
Firefox 目前忽略這個參數,但未來可能會用到。在此處傳一個空字符串應該可以安全的防范未來這個方法的更改。或者,你可以為跳轉的state傳遞一個短標題。
URL
新的歷史URL記錄。新URL不必須為絕對路徑。如果新URL是相對路徑,那么它將被作為相對于當前URL處理。新URL必須與當前URL同源,否則 pushState() 會拋出一個異常。該參數是可選的,缺省為當前URL。
注意: pushState() 絕對不會觸發 hashchange 事件,即使新的URL與舊的URL僅哈希不同也是如此。
更改歷史記錄中的當前條目不會立即加載頁面的情況下改變了當前URL地址,并改變歷史記錄的當前條目,除非刷新頁面等操作
history.replaceState(state, title , URL);popstate 事件每當活動的歷史記錄項發生變化時, popstate 事件都會被傳遞給window對象。如果當前活動的歷史記錄項是被 pushState 創建的,或者是由 replaceState 改變的,那么 popstate 事件的狀態屬性 state 會包含一個當前歷史記錄狀態對象的拷貝。
獲取當前狀態頁面加載時,或許會有個非null的狀態對象。這是有可能發生的,舉個例子,假如頁面(通過pushState() 或 replaceState() 方法)設置了狀態對象而后用戶重啟了瀏覽器。那么當頁面重新加載時,頁面會接收一個onload事件,但沒有 popstate 事件。然而,假如你讀取了history.state屬性,你將會得到如同popstate 被觸發時能得到的狀態對象。
你可以讀取當前歷史記錄項的狀態對象state,而不必等待popstate 事件
思路監聽點擊事件禁止默認跳轉操作,手動利用history實現一套跳轉邏輯,根據location.pathname渲染界面.
Document 具體代碼可以查看html5_demo.html
注意,該方法不支持本地運行,只能線上運作或者啟動服務器查看效果html5_demo.html:26 Uncaught DOMException: Failed to execute "pushState" on "History": A history state object with URL "file:///C:/b" cannot be created in a document with origin "null" and URL "file:///C:/work/project/router_demo/src/html5_demo.html". at HTMLAnchorElement.簡單封裝路由庫 API(file:///C:/work/project/router_demo/src/html5_demo.html:26:15) (anonymous) @ html5_demo.html:26 基本的路由方法:
router.push(url, onComplete)
router.replace(url, onComplete)
router.go(n)
router.back()
router.stop()
router 初始化
- console.log("push a"))">push a
- console.log("push b"))">push b
- console.log("replace c"))">replace c
- go
- back
- stop
import Router from "../router" window.router = new Router("view", { routes: [ { path: "/a", component: "router類a
" }, { path: "/b", component: "b
" }, { path: "/c", component: "c
" }, { path: "*", redirect: "/index" } ] }, "hash")// 或者"html5"import HashHstory from "./HashHistory"; import Html5History from "./Html5History"; export default class Router { constructor(wrapper, options, mode = "hash") { this._wrapper = document.querySelector(`#${wrapper}`) if (!this._wrapper) { throw new Error(`你需要提供一個容器元素插入`) } // 是否支持HTML5 History 模式 this._supportsReplaceState = window.history && typeof window.history.replaceState === "function" // 匹配路徑 this._cache = {} // 默認路由 this._defaultRouter = options.routes[0].path this.route(options.routes) // 啟用模式 this._history = (mode !== "hash" && this._supportsReplaceState) ? new Html5History(this, options) : new HashHstory(this, options) } // 添加路由 route(routes) { routes.forEach(item => this._cache[item.path] = item.component) } // 原生瀏覽器前進 go(n = 1) { window.history.go(n) } // 原生瀏覽器后退 back(n = -1) { window.history.go(n) } // 增加 push(url, onComplete) { this._history.push(url, onComplete) } // 替換 replace(url, onComplete) { this._history.replace(url, onComplete) } // 移除事件 stop() { this._history.stop() } }Hash Classexport default class HashHistory { constructor(router, options) { this.router = router this.onComplete = null // 監聽事件 window.addEventListener("load", this.onChange) window.addEventListener("hashchange", this.onChange) } onChange = () => { // 匹配失敗重定向 if (!location.hash || !this.router._cache[location.hash.slice(1)]) { window.location.hash = this.router._defaultRouter } else { // 渲染視圖 this.router._wrapper.innerHTML = this.router._cache[location.hash.slice(1)] this.onComplete && this.onComplete() && (this.onComplete = null) } } push(url, onComplete) { window.location.hash = `${url}` onComplete && (this.onComplete = onComplete) } replace(url, onComplete) { // 優雅降級 if (this.router._supportsReplaceState) { window.location.hash = `${url}` window.history.replaceState(null, null, `${window.location.origin}#${url}`) } else { // 需要先看看當前URL是否已經有hash值 const href = location.href const index = href.indexOf("#") url = index > 0 ? `${href.slice(0, index)}#${url}` : `${href}#${url}` // 域名不變的情況下不會刷新頁面 window.location.replace(url) } onComplete && (this.onComplete = onComplete) } // 移除事件 stop() { window.removeEventListener("load", this.onChange) window.removeEventListener("hashchange", this.onChange) } }HTML5 Classexport default class Html5Hstory { constructor(router, options) { this.addEvent() this.router = router this.onComplete = null // 監聽事件 window.addEventListener("popstate", this.onChange) window.addEventListener("load", this.onChange) window.addEventListener("replaceState", this.onChange); window.addEventListener("pushState", this.onChange); } // pushState/replaceState不會觸發popstate事件,所以我們需要自定義 addEvent() { const listenWrapper = function (type) { const _func = history[type]; return function () { const func = _func.apply(this, arguments); const e = new Event(type); e.arguments = arguments; window.dispatchEvent(e); return func; }; }; history.pushState = listenWrapper("pushState"); history.replaceState = listenWrapper("replaceState"); } onChange() { // 匹配失敗重定向 if (location.pathname === "/" || !this.router._cache[location.pathname]) { window.history.pushState(null, "", `${window.location.origin}${this.router._defaultRouter}`); } else { // 渲染視圖 this.router._wrapper.innerHTML = this.router._cache[location.pathname] this.onComplete && this.onComplete() && (this.onComplete = null) } } push(url, onComplete) { window.history.pushState(null, "", `${window.location.origin}${url}`); onComplete && (this.onComplete = onComplete) } replace(url, onComplete) { window.history.replaceState(null, null, `${window.location.origin}${url}`) onComplete && (this.onComplete = onComplete) } // 移除事件 stop() { window.removeEventListener("load", this.onChange) window.removeEventListener("popstate", this.onChange) window.removeEventListener("replaceState", this.onChange) window.removeEventListener("pushState", this.onChange) } }完整代碼可以拷貝router_demo
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/106464.html
摘要:我們在回到的構造函數中,往下看是模式的選擇,一共這么幾種模式一種和三種。把我們繼續回到中,首先繼承構造函數。表示信息,表示成功后的回調函數,表示失敗的回調函數。是三種的實例對象,然后分情況進行操作,方法就是給賦值穿進去的回調函數。 如同分析vuex源碼我們首先通過一個簡單例子進行了解vue-router是如何使用的,然后在分析在源碼中是如何實現的 示例 下面示例來自于example/b...
摘要:而路由則是使用了中新增的事件和事件。總結這一章主要是介紹了如何使用在中構建我們的前端路由。 系列目錄地址 一、基礎知識概覽 第一章 - 一些基礎概念(posted at 2018-10-31) 第二章 - 常見的指令的使用(posted at 2018-11-01) 第三章 - 事件修飾符的使用(posted at 2018-11-02) 第四章 - 頁面元素樣式的設定(posted a...
摘要:源碼解讀閱讀請關注下代碼注釋打個廣告哪位大佬教我下怎么排版啊,不會弄菜單二級導航撲通是什么首先,你會從源碼里面引入,然后再傳入參數實例化一個路由對象源碼基礎類源碼不選擇模式會默認使用模式非瀏覽器環境默認環境根據參數選擇三種模式的一種根據版 router源碼解讀 閱讀請關注下代碼注釋 打個廣告:哪位大佬教我下sf怎么排版啊,不會弄菜單二級導航(撲通.gif) showImg(https:...
摘要:源碼解讀閱讀請關注下代碼注釋打個廣告哪位大佬教我下怎么排版啊,不會弄菜單二級導航撲通是什么首先,你會從源碼里面引入,然后再傳入參數實例化一個路由對象源碼基礎類源碼不選擇模式會默認使用模式非瀏覽器環境默認環境根據參數選擇三種模式的一種根據版 router源碼解讀 閱讀請關注下代碼注釋 打個廣告:哪位大佬教我下sf怎么排版啊,不會弄菜單二級導航(撲通.gif) showImg(https:...
閱讀 3247·2021-09-22 15:58
閱讀 1717·2019-08-30 14:17
閱讀 1716·2019-08-28 18:05
閱讀 1505·2019-08-26 13:33
閱讀 683·2019-08-26 12:20
閱讀 606·2019-08-26 12:18
閱讀 3192·2019-08-26 11:59
閱讀 1401·2019-08-26 10:36