第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

發(fā)出 AJAX HTTP GET 請求后,如何處理瀏覽器刷新按鈕的這種破壞行為?

發(fā)出 AJAX HTTP GET 請求后,如何處理瀏覽器刷新按鈕的這種破壞行為?

郎朗坤 2023-05-19 16:21:13
我依靠“AJAX 調(diào)用”編寫我的第一個單頁網(wǎng)站大約一個星期,認為這些會給我一個“SPA”,然而,在某些時候,當我點擊頂部的刷新按鈕時 [純粹是運氣],我看到的是最新的AJAX調(diào)用的字符串結(jié)果,在瀏覽器的白頁上,而不是我網(wǎng)站的HTML頁面!實際上,原因是我將瀏覽器的 URL 更改為window.history.pushState,然后請求直接發(fā)送到后端,而不是通過我的 JavaScript 代碼。事情(盲目嘗試)到目前為止我已經(jīng)嘗試過(TL; DR-Caution:他們都沒有工作):我以為我能做的第一件事就是刪除歷史記錄!但是,這似乎不可能(單個重定向除外)。否則,如果一個網(wǎng)站可以欺負用戶其他網(wǎng)站的歷史記錄,則可能會導致明顯的隱私問題!下一個想法是改變?yōu)g覽器的歷史。我認為也許只將主頁(包裝所有為 AJAX 響應創(chuàng)建的 DOM 元素的頁面)注入到 將使window.history瀏覽器忽略接下來發(fā)生的任何其他事情。我錯了。我還想到了將整個 DOM 元素存儲在一個變量中并將其推送到 的丑陋解決方案window.history,但隨后檢測刷新事件并將其與直接訪問區(qū)分開來將是下一個挑戰(zhàn)。我還嘗試監(jiān)聽 beforeunload 事件,試圖阻止刷新,然后自己更改位置(這樣聽起來像是實際刷新),但是在單擊刷新按鈕后更改瀏覽器的 url,因此新URL獲勝當點擊刷新按鈕時,'影響瀏覽器已經(jīng)向其發(fā)送請求的路由。那么有沒有一種方法可以用 vanilla JavaScript 來處理這個問題?或者也許我誤會了一些簡單的事情?或者更好的解決方案是使用 React、VueJS 等工具來“更輕松”地完成我的 SPA?這些工具都沒有問題,我只是更喜歡更簡單的方法。我想要的 SPA 類似于MongoDB 網(wǎng)站的文檔頁面。編輯:代碼:xhr.onreadystatechange = function () {        if (xhr.readyState === 4) {          if (xhr.status === 200) {            data = JSON.parse(xhr.responseText);            content_box.innerHTML = data.content;            window.history.pushState({"content":data.content, "title": data.title + " | App Manual"}, data.title + " | App Manual", href); 
查看完整描述

1 回答

?
莫回無

TA貢獻1865條經(jīng)驗 獲得超7個贊

代碼非常簡單(盡管可以使用 fetch 或更簡潔的 XHR 實現(xiàn)進一步簡化)。

HTML

這里只有兩件事與我們有關(guān)。一個是#content-box,我們將從我們的 API 加載的任何內(nèi)容放置在這里。在我的版本中,它看起來像這樣:

<section?id="content_box"></section>

另一個是a用于內(nèi)部路由的元素,它們必須具有link與之關(guān)聯(lián)的類,如下所示:

<ul>

? <li><a class="link" href="/section-1">Link #1</a></li>

? <li><a class="link" href="/section-2">Link #2</a></li>

</ul>

JS

我們從一般變量的一些基本初始化開始:


const useHash = true;

const apiUrl = 'https://lucasreta.com/stack-overflow/spa-vanilla-js/api';

const routes = ['section-1', 'section-2'];

const content_box = document.getElementById("content_box");

useHash將決定我們是否應該使用 URL 的錨點(哈希),或者我們內(nèi)部路由的最后一個參數(shù)。


apiUrl設(shè)置我們簡單 API 的基本 URL。


routes定義我們應用程序的有效路徑。


content_box是我們將在沒有數(shù)據(jù)的情況下更新的 DOM 元素。


然后我們定義我們的異步信息獲取器,它仍然是一個非常標準的 XHR 調(diào)用,類似于您已經(jīng)擁有的(缺少錯誤處理):


function get(page) {

? const xhr = new XMLHttpRequest();

? xhr.onreadystatechange = function() {

? ? if (this.readyState == 4 && this.status == 200) {

? ? ? data = JSON.parse(xhr.responseText);

? ? ? content_box.innerHTML = data.content;

? ? ? const title = `${data.title} | App Manual`;

? ? ? window.history.pushState(

? ? ? ? { 'content': data.content, 'title': title},

? ? ? ? title,

? ? ? ? useHash ?

? ? ? ? ? `#${page}` :

? ? ? ? ? page

? ? ? );

? ? }

? };

? xhr.open('GET', `${apiUrl}/${page}`, true);

? xhr.send();

}

在這里,我們向我們的get函數(shù)發(fā)送一個名為 的參數(shù)page,該參數(shù)與我們將使用的 API 的端點以及我們將在狀態(tài)和 URL 中使用的名稱相匹配,以確定我們必須顯示的內(nèi)容。


鑒于您在代碼中顯示的響應對象的簡單性,我認為將整個內(nèi)容和標題對象推入我們的歷史并稍后從那里使用它是合適的。在更復雜的場景中,我們可能只需要存儲page參數(shù)并向 API 發(fā)出新請求。


現(xiàn)在我們必須處理修改單頁應用程序狀態(tài)的三個事件:


// add event listener to links

const links = document.getElementsByClassName('link');

for(let i = 0; i < links.length; i++) {

? links[i].addEventListener('click', function(event) {

? ? event.preventDefault();

? ? get(links[i].href.split('/').pop());

? }, false);

}


// add event listener to history changes

window.addEventListener("popstate", function(e) {

? const state = e.state;

? content_box.innerHTML = state.content;

});


// add ready event for initial load of our site

(function(fn = function() {

? const page = useHash ?

? ? window.location.hash.split('#').pop() :

? ? window.location.href.split('/').pop();

? get(routes.indexOf(page) >= 0 ? page : routes[0]);

}) {

? if (document.readyState != 'loading'){

? ? fn();

? } else {

? ? document.addEventListener('DOMContentLoaded', fn);

? }

})();

首先,我們獲取所有具有類的元素.link并為它們附加一個事件偵聽器,以便在單擊它們時停止默認事件,而是get使用 href 的最后一個參數(shù)調(diào)用我們的函數(shù)。

因此,當我們單擊上面列出的第一個鏈接時,我們將執(zhí)行 GET 請求并將api.com/section-1我們應用程序的 URL 更新為app.com/section-1app.com/#section-1。

我的實施有兩個局限性:

  • API 和應用路由必須匹配。

  • 路由不能有多個參數(shù)。

兩者都是可修復的,我不會詳細介紹,因為它脫離了簡單 POC 的要點,但我必須指出這一點。第一個可以通過使用某種字典來修復,該字典將我們的路由匹配到它們應該獲取的端點。第二個問題可以通過在我們的鏈接事件偵聽器中使邏輯更復雜一些來解決,擴展簡單links[i].href.split('/').pop()以包括所有預期的參數(shù)。

接下來我們有歷史變化的事件監(jiān)聽器。由于我們將 API 返回的內(nèi)容存儲在歷史狀態(tài)本身中,所以當歷史發(fā)生變化時,我們所要做的就是content_box用我們的state.content.

最后,我們有 ready 函數(shù),在 DOM 最初結(jié)束加載時調(diào)用:

我們檢查我們的 URL 以獲取最后一個參數(shù)或散列/錨點的值。然后我們驗證我們從 URL 獲得的內(nèi)容是否存在于我們定義的內(nèi)部路由數(shù)組中。如果是這樣,我們將get其作為參數(shù)調(diào)用我們的函數(shù)。如果沒有,我們就從數(shù)組中獲取第一條路線并用它來調(diào)用它。


查看完整回答
反對 回復 2023-05-19
  • 1 回答
  • 0 關(guān)注
  • 116 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號