摘要:顯示為顯示為顯示為單頁(yè)面應(yīng)用用戶(hù)訪問(wèn)軌跡埋點(diǎn)開(kāi)發(fā)過(guò)單頁(yè)面應(yīng)用的同學(xué),一定比較清楚,單頁(yè)面應(yīng)用的路由切換是無(wú)感知的,不會(huì)重新進(jìn)行請(qǐng)求去獲取頁(yè)面,而是通過(guò)改變頁(yè)面渲染視圖來(lái)實(shí)現(xiàn)。
前言
最近開(kāi)發(fā)的埋點(diǎn)項(xiàng)目,需要記錄用戶(hù)行為軌跡即用戶(hù)頁(yè)面訪問(wèn)順序。需要在頁(yè)面跳轉(zhuǎn)的時(shí)候,記錄用戶(hù)訪問(wèn)的信息(比如 url ,請(qǐng)求頭部等),非單頁(yè)面應(yīng)用可以給 window 對(duì)象加上一個(gè) beforeunload 事件,在頁(yè)面離開(kāi)時(shí)觸發(fā)采集開(kāi)關(guān),但是現(xiàn)在很多業(yè)務(wù)是單頁(yè)面應(yīng)用,用戶(hù)切換地址的時(shí)候,是無(wú)刷新的局部更新,沒(méi)有辦法觸發(fā) beforeunload。所以單頁(yè)面應(yīng)用的路由插件一定運(yùn)用了 window 自帶的,無(wú)刷新修改用戶(hù)瀏覽記錄的方法,pushState 和 replaceState。
pushState 和 replaceState 了解一下history 提供了兩個(gè)方法,能夠無(wú)刷新的修改用戶(hù)的瀏覽記錄,pushSate,和 replaceState,區(qū)別的 pushState 在用戶(hù)訪問(wèn)頁(yè)面后面添加一個(gè)訪問(wèn)記錄, replaceState 則是直接替換了當(dāng)前訪問(wèn)記錄
history 對(duì)象的詳細(xì)信息已經(jīng)有很多很好很詳細(xì)的介紹文獻(xiàn),這里不再做總結(jié),我們引用阮老師的教程介紹,history對(duì)象 -- JavaScript 標(biāo)準(zhǔn)參考教程(alpha)
history.pushStatehistory.pushState方法接受三個(gè)參數(shù),依次為:
state:一個(gè)與指定網(wǎng)址相關(guān)的狀態(tài)對(duì)象,popstate事件觸發(fā)時(shí),該對(duì)象會(huì)傳入回調(diào)函數(shù)。如果不需要這個(gè)對(duì)象,此處可以填null。
title:新頁(yè)面的標(biāo)題,但是所有瀏覽器目前都忽略這個(gè)值,因此這里可以填null。
url:新的網(wǎng)址,必須與當(dāng)前頁(yè)面處在同一個(gè)域。瀏覽器的地址欄將顯示這個(gè)網(wǎng)址。
假定當(dāng)前網(wǎng)址是example.com/1.html,我們使用pushState方法在瀏覽記錄(history對(duì)象)中添加一個(gè)新記錄。
var stateObj = { foo: "bar" }; history.pushState(stateObj, "page 2", "2.html");
添加上面這個(gè)新記錄后,瀏覽器地址欄立刻顯示 example.com/2.html,但并不會(huì)跳轉(zhuǎn)到 2.html,甚至也不會(huì)檢查2.html 是否存在,它只是成為瀏覽歷史中的最新記錄。這時(shí),你在地址欄輸入一個(gè)新的地址(比如訪問(wèn) google.com ),然后點(diǎn)擊了倒退按鈕,頁(yè)面的 URL 將顯示 2.html;你再點(diǎn)擊一次倒退按鈕,URL 將顯示 1.html。
總之,pushState 方法不會(huì)觸發(fā)頁(yè)面刷新,只是導(dǎo)致 history 對(duì)象發(fā)生變化,地址欄會(huì)有反應(yīng)。
如果 pushState 的 url參數(shù),設(shè)置了一個(gè)新的錨點(diǎn)值(即hash),并不會(huì)觸發(fā) hashchange 事件。如果設(shè)置了一個(gè)跨域網(wǎng)址,則會(huì)報(bào)錯(cuò)。
history.replaceState// 報(bào)錯(cuò) history.pushState(null, null, "https://twitter.com/hello"); 上面代碼中,pushState想要插入一個(gè)跨域的網(wǎng)址,導(dǎo)致報(bào)錯(cuò)。這樣設(shè)計(jì)的目的是,防止惡意代碼讓用戶(hù)以為他們是在另一個(gè)網(wǎng)站上。
history.replaceState 方法的參數(shù)與 pushState 方法一模一樣,區(qū)別是它修改瀏覽歷史中當(dāng)前紀(jì)錄,假定當(dāng)前網(wǎng)頁(yè)是 example.com/example.html。
單頁(yè)面應(yīng)用用戶(hù)訪問(wèn)軌跡埋點(diǎn)history.pushState({page: 1}, "title 1", "?page=1"); history.pushState({page: 2}, "title 2", "?page=2"); history.replaceState({page: 3}, "title 3", "?page=3"); history.back() // url顯示為http://example.com/example.html?page=1 history.back() // url顯示為http://example.com/example.html history.go(2) // url顯示為http://example.com/example.html?page=3
開(kāi)發(fā)過(guò)單頁(yè)面應(yīng)用的同學(xué),一定比較清楚,單頁(yè)面應(yīng)用的路由切換是無(wú)感知的,不會(huì)重新進(jìn)行 http 請(qǐng)求去獲取頁(yè)面,而是通過(guò)改變頁(yè)面渲染視圖來(lái)實(shí)現(xiàn)。所以他的實(shí)現(xiàn)原理一定也是通過(guò)原生的 pushState 或則 replaceState 來(lái)實(shí)現(xiàn)的。所以在頁(yè)面跳轉(zhuǎn)的時(shí)候一定會(huì)調(diào)用 pushState 或則 replaceState ,要記錄用戶(hù)的跳轉(zhuǎn)信息,我們只要攔截 pushState 和 replaceState,在執(zhí)行默行為前先執(zhí)行我們的方法就能夠采集到用戶(hù)的跳轉(zhuǎn)信息了
vue-router 的路由實(shí)現(xiàn)// 改寫(xiě)思路:拷貝 window 默認(rèn)的 replaceState 函數(shù),重寫(xiě) history.replaceState 在方法里插入我們的采集行為,在重寫(xiě)的 replaceState 方法最后調(diào)用,window 默認(rèn)的 replaceState 方法 collect = {} collect.onPushStateCallback : function(){} // 自定義的采集方法 (function(history){ var replaceState = history.replaceState; // 存儲(chǔ)原生 replaceState history.replaceState = function(state, param) { // 改寫(xiě) replaceState var url = arguments[2]; if (typeof collect.onPushStateCallback == "function") { collect.onPushStateCallback({state: state, param: param, url: url}); //自定義的采集行為方法 } return replaceState.apply(history, arguments); // 調(diào)用原生的 replaceState }; })(window.history);
既然知道了這個(gè)原理,我們來(lái)看下 vue-router 的實(shí)現(xiàn),我們打開(kāi) vue-router 項(xiàng)目地址,把項(xiàng)目克隆下來(lái),或則直接在 github 上預(yù)覽,在 Vue 開(kāi)發(fā)的項(xiàng)目里,我們通過(guò) router.push("home") 來(lái)實(shí)現(xiàn)頁(yè)面的跳轉(zhuǎn),所以我們檢索下,push 方法的實(shí)現(xiàn)
我們檢索到了 20 個(gè) js 文件,
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/107749.html
摘要:而路由則是使用了中新增的事件和事件??偨Y(jié)這一章主要是介紹了如何使用在中構(gòu)建我們的前端路由。 系列目錄地址 一、基礎(chǔ)知識(shí)概覽 第一章 - 一些基礎(chǔ)概念(posted at 2018-10-31) 第二章 - 常見(jiàn)的指令的使用(posted at 2018-11-01) 第三章 - 事件修飾符的使用(posted at 2018-11-02) 第四章 - 頁(yè)面元素樣式的設(shè)定(posted a...
摘要:出于安全的考慮,開(kāi)發(fā)人員無(wú)法得知用戶(hù)瀏覽過(guò)的。這個(gè)方法接受一個(gè)參數(shù),表示向后或向前跳轉(zhuǎn)的頁(yè)面數(shù)的一個(gè)整數(shù)值。該事件觸發(fā)時(shí),該對(duì)象會(huì)傳入回調(diào)函數(shù)。假定當(dāng)前網(wǎng)頁(yè)是。顯示為顯示為顯示為顯示為顯示為顯示為三事件事件是對(duì)象上的事件,配合和方法使用。 首先要學(xué)習(xí)一下history對(duì)象,history對(duì)象保存著用戶(hù)的上網(wǎng)記錄,從瀏覽器窗口打開(kāi)的那一刻算起。出于安全的考慮,開(kāi)發(fā)人員無(wú)法得知用戶(hù)瀏覽過(guò)的...
摘要:談起閉包,它可是兩個(gè)核心技術(shù)之一異步基于打造前端持續(xù)集成開(kāi)發(fā)環(huán)境本文將以一個(gè)標(biāo)準(zhǔn)的項(xiàng)目為例,完全拋棄傳統(tǒng)的前端項(xiàng)目開(kāi)發(fā)部署方式,基于容器技術(shù)打造一個(gè)精簡(jiǎn)的前端持續(xù)集成的開(kāi)發(fā)環(huán)境。 這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制 本文的目的就是要保證你徹底弄懂javascript的執(zhí)行機(jī)制,如果讀完本文還不懂,可以揍我。 不論你是javascript新手還是老鳥(niǎo),不論是面試求職,還是日...
摘要:路由模塊的本質(zhì)就是建立起和頁(yè)面之間的映射關(guān)系。模式的原理是事件監(jiān)測(cè)值變化,可以在對(duì)象上監(jiān)聽(tīng)這個(gè)事件。這兩個(gè)方法應(yīng)用于瀏覽器記錄棧,在當(dāng)前已有的基礎(chǔ)之上,它們提供了對(duì)歷史記錄修改的功能。 vue-router 這里的路由并不是指我們平時(shí)所說(shuō)的硬件路由器,這里的路由就是SPA(單頁(yè)應(yīng)用)的路徑管理器。再通俗的說(shuō),vue-router就是WebApp的鏈接路徑管理系統(tǒng)。vue-router是...
showImg(https://segmentfault.com/img/bVbvOmp?w=1612&h=888); 隨著React Vue前端框架的興起,出現(xiàn)了Vue-router,react-router-dom等前端路由管理庫(kù),利用他們構(gòu)建出來(lái)的單頁(yè)面應(yīng)用,也是越來(lái)越接近原生的體驗(yàn),再也不是以前的點(diǎn)擊標(biāo)簽跳轉(zhuǎn)頁(yè)面,刷新整個(gè)頁(yè)面了,那么他們的原理是什么呢? 優(yōu)質(zhì)gitHub開(kāi)源練手項(xiàng)目: ...
閱讀 1398·2021-11-17 09:33
閱讀 2002·2021-09-09 11:53
閱讀 3512·2021-09-04 16:45
閱讀 1580·2021-08-17 10:12
閱讀 2577·2019-08-30 15:55
閱讀 1851·2019-08-30 15:53
閱讀 2481·2019-08-30 15:52
閱讀 2642·2019-08-29 18:41