巧用location.hash保存頁面狀態

来源:http://www.cnblogs.com/leotsai/archive/2016/04/27/using-location-hash-to-store-page-statuses.html
-Advertisement-
Play Games

在我們的項目中,有大量ajax查詢表單+結果列表的頁面,由於查詢結果是ajax返回的,當用戶點擊列表的某一項進入詳情頁之後,再點擊瀏覽器回退按鈕返回ajax查詢頁面,這時大家都知道查詢頁面的表單和結果都回到了預設狀態。 如果每次返回頁面都要重新輸入查詢條件,或有甚者還得轉到列表的第幾頁,那這種體驗用 ...


在我們的項目中,有大量ajax查詢表單+結果列表的頁面,由於查詢結果是ajax返回的,當用戶點擊列表的某一項進入詳情頁之後,再點擊瀏覽器回退按鈕返回ajax查詢頁面,這時大家都知道查詢頁面的表單和結果都回到了預設狀態。

 

如果每次返回頁面都要重新輸入查詢條件,或有甚者還得轉到列表的第幾頁,那這種體驗用戶真的要抓狂了。

 

在我們的項目中,寫了一個很簡單的JavaScript基類來處理location.hash從而保存頁面狀態,今天在此就分享給大家。

 

(本文的內容可能對於JavaScript初學者來講有點難度,因為涉及到JS面向對象的知識,如定義類、繼承、虛方法、反射等)

 

先看看我們的需求

我們的項目是一個基於微信的H5任務管理系統,要完成的頁面原型如下圖所示:

 

需求應該都很清晰,就是點擊查詢表單,用ajax返回查詢結果,然後點擊列表中的某一個任務進入任務詳情頁。由於管理員(項目經理)通常會一次處理多個任務,所以就會不斷在任務詳情頁跟查詢列表頁切換,這時如果按返回鍵不能保存查詢頁面狀態的話,那每次返回查詢頁面都要重新輸入查詢條件,這樣的體驗肯定是不能忍受的。

 

所以,我們需要想辦法將頁面狀態保存下來,以便用戶按回退鍵的時候,查詢條件和結果都還在。

 

解決思路

保存頁面狀態的思路有很多啦,但是我們覺得用location.hash應該是最好的方法。

 

思路如下:

 

  1. 用戶輸入查詢條件並點擊確定後,我們將查詢條件序列化成一個字元串,並通過“#”將查詢條件加到url後面得到一個新的url,然後調用location.replace(新的url)修改瀏覽器地址欄中的地址。
  2. 當用戶按回退鍵回退到查詢頁面時,也可以說是頁面載入時,將location.hash反序列化成查詢條件,然後將查詢條件更新到查詢表單並執行查詢即可。

 

思路很簡單,關鍵的地方就是location.replace方法,這個方法不僅僅是修改瀏覽器中地址欄的url,更重要的是會在window.history中替換當前頁面的記錄。如果不用location.replace方法,那麼每次回退都會回退到上一個查詢條件。當然,這樣的需求可能對某些項目還有用。

 

最終解決方案

 如果本文只是分享上面的解決思路,那價值就不大了。本文的價值應該是我們寫的那個雖然簡單但是卻很強大的JavaScript類。

 

如果你看明白了上面的解決思路,那就看看這個簡單的JavaScript類吧:

 1 (function() {
 2     if (window.HashQuery) {
 3         return;
 4     }
 5     window.HashQuery = function() {
 6 
 7     };
 8 
 9     HashQuery.prototype = {
10         parseFromLocation: function() {
11             if (location.hash === '' || location.hash.length === 1) {
12                 return;
13             }
14             var properties = location.hash.substr(1).split('|');
15             var index = 0;
16             for (var p in this) {
17                 if (!this.hasOwnProperty(p) || typeof this[p] != 'string') {
18                     continue;
19                 }
20 
21                 if (index < properties.length) {
22                     this[p] = properties[index];
23                     if (this[p] === '-') {
24                         this[p] = '';
25                     }
26                 }
27                 index++;
28             }
29         },
30         updateLocation: function() {
31             var properties = [];
32             for (var p in this) {
33                 if (!this.hasOwnProperty(p) || typeof this[p] != 'string') {
34                     continue;
35                 }
36                 var value = this[p];
37                 properties.push(value === '' ? '-' : value);
38             }
39             var url = location.origin + location.pathname + location.search + "#" + properties.join('|');
40             location.replace(url);
41         }
42     };
43 })();

 

這個類只有2個方法,HashQuery.parseFromLocation() 方法從location.hash反序列化為HashQuery子類的實例,HashQuery.updateLocation() 方法將當前HashQuery子類的實例序列化並更新到window.location。

 

可以看到HashQuery這個類沒有任何屬性,那是因為我們只定義了一個基類,類的屬性都在子類中進行定義。這也是符合實際的,因為查詢條件都只有在具體的頁面才知道有哪些屬性。

 

另外,請註意這裡的序列化和反序列化。這裡的序列化僅僅是利用JavaScript反射機制將實例的所有字元串屬性(按順序)的值用“|”分隔;而序列化則是將字元串用“|”分隔後,再利用反射更新到實例的屬性(按順序)。

 

如何使用HashQuery類

使用的時候就非常簡單了。

 

第一步,定義一個子類,將需要用到的查詢條件都加到字元串屬性當中,如我們的代碼:

 1 (function() {
 2     window.TaskSearchHashQuery = function () {
 3         HashQuery.constructor.call(this);
 4         this.iterationId = '';
 5         this.assignedUserId = '';
 6         this.status = '';
 7         this.keyword = '';
 8     };
 9 
10     TaskSearchHashQuery.constructor = TaskSearchHashQuery;
11     TaskSearchHashQuery.prototype = new HashQuery();
12 })();

 

第二步,在查詢頁面調用HashQuery.parseFromLocation() 和 HashQuery.updateLocation()方法即可。下麵的代碼是我們完整的查詢頁面:

 1 (function() {
 2     var urls = {
 3         list: "/app/task/list"
 4     };
 5     var hashQuery = null;
 6     var pager = null;
 7 
 8     $(document).ready(function () {
 9         hashQuery = new TaskSearchHashQuery();
10         hashQuery.parseFromLocation();//在這裡調用的哦,從location反序列化object
11         updateFormByHashQuery();
12 
13         $("#btnSearch").click(function() {
14             updateHashQueryByForm();
15             hashQuery.updateLocation();//在這裡調用的哦,將查詢條件序列化之後更新到location.hash
16             $("#lblCount").html("載入中...");
17             pager.reload();
18             page.hideSearch();
19         });
20 
21         pager = new ListPager("#listTasks", urls.list);
22         pager.getPostData = function(index) {
23             return "pageIndex=" + index + "&pageSize=50" + "&projectId=" + page.projectId
24                 + "&iterationId=" + hashQuery.iterationId
25                 + "&assignedUserId=" + hashQuery.assignedUserId
26                 + "&status=" + hashQuery.status
27                 + "&keyword=" + hashQuery.keyword;
28         };
29         pager.onLoaded = function() {
30             $("#lblCount").html("共 " + $("#hfPagerTotalCount").val() + " 個任務");
31             $("#hfPagerTotalCount").remove();
32         };
33         pager.init();
34     });
35 
36     function updateHashQueryByForm() {
37         hashQuery.iterationId = $("#ddlIterations").val();
38         hashQuery.assignedUserId = $("#ddlUsers").val();
39         hashQuery.status = $("#ddlStatuses").val();
40         hashQuery.keyword = $("#txtKeyword").val();
41     };
42 
43     function updateFormByHashQuery() {
44         $("#ddlIterations").val(hashQuery.iterationId);
45         $("#ddlUsers").val(hashQuery.assignedUserId);
46         $("#ddlStatuses").val(hashQuery.status);
47         $("#txtKeyword").val(hashQuery.keyword);
48     };
49 
50 })();

 

總結

這就是我們項目中使用location.hash來保存頁面狀態的全部知識了。不知道大家的WEB項目中是如何處理這樣的需求的呢?

 

最後,大家可以看看我們的開源項目:https://github.com/leotsai/mvcsolution,一個講ASP.NET MVC應用架構的項目,裡面也有不少JavaScript的架構和高級用法。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • × 目錄 [1]line-height [2]vertical-align [3]absolute [4]flex 前面的話 相對於水平居中,人們對於垂直居中略顯為難,大部分原因是vertical-align不能正確使用。實際上,實現垂直居中也是圍繞幾個思路展開的。本文將介紹關於垂直居中的4種思路 ...
  • 這個算是 Chrome only 其他的我沒測試,也不想測試。因為我的控制台腳本僅僅在 Chrome 下載入。 如果你需要全平臺,那麼這肯定不是你需要的結果。 <! more 需求 其實我很早就想折騰這個了,但是,,因為懶,拖了很久,直到周末,我看到伺服器上統計,發現流量翻了一倍,結果訪問量還是一樣 ...
  • 在做項目的過程中遇到了需要將圖像作為背景,將字體顯示在圖像中央需求。 嘗試了兩種做法: 第一種方法為設置一個div設置屬性為relative固定這個框的位置,將圖片鋪在div塊里。 在div再設一個div存放字體,z-index設置為2,及圖片在下麵,字體在上面,字框的屬性設置為absoulte(絕 ...
  • 解決辦法:給img定義vertical align或者定義為塊狀。 最優的解決辦法是:定義vertical align,註:定義vertical align為middle時在IE6中大概還有一像素的頂邊距,最好為top或bottom。 還有種極端解決辦法就是:將父容器的字體大小為零,font siz ...
  • 有三種方法能夠確定瀏覽器視窗的尺寸(瀏覽器的視口,不包括工具欄和滾動條)。 對於Internet Explorer、Chrome、Firefox、Opera 以及 Safari: 瀏覽器視窗的內部高度:window.innerHeight 瀏覽器視窗的內部寬度:window.innerWidth 對 ...
  • 今天,開始學習第二節!!! 工欲善其事,必先利其器 react推薦我們使用webpack來打包文件,那麼我們就用吧!(其實真心不想用啊) 至於好處網上寫的天花亂墜的,大家自行解決啊... 這節主要就學習怎麼配置webpack了,這玩意我搗鼓了整整一天才弄的一知半解,哎,腦子差就是吃虧... 1.提前 ...
  • 在寫這篇文章之前,我詢問了在唯品會和騰訊的童鞋、以及公司裡面前端大神(深哥),對於設計稿切圖的詳細方法,經過對比驗證,得出設計稿轉換頁面單位尺寸方法步驟。我分別詢問下麵四個問題: 1. 設計稿的單位是什麼,一般大小是什麼? 2. 頁面長度單位用什麼,px、em、rem,還是混合,如果用rem,htm ...
  • 查看效果:http://hovertree.com/texiao/mobile/10/或者手機掃描二維碼查看效果: 效果圖:代碼如下: 轉自:http://hovertree.com/h/bjaf/loucldil.htm 推薦:http://hovertree.com/hvtart/bjae/jf ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...