搜尋
首頁web前端H5教程使用ASP.NET MVC构建HTML5离线web应用程序

       web应用程序的主要制约之一就是连接性。在HTML5到来之前我们就曾想挖掘浏览器的能力,以使web应用程序能像桌面应用程序一样功能强大和易于使用,但浏览器始终让我们感到失望。虽然之前已出现了一些浏览器缓存技术,但这些缓存技术的设计初衷并不是为了使web应用程序能够完全地离线运行,令人遗憾的是,事实上使用这些技术的web应用程序很容易出问题,而且难于使用。HTML5试图通过离线应用程序缓存( offline application cache)技术来填补浏览器的能力空缺,该技术能更加可靠地使web应用程序离线工作。

       为什么web应用程序需要离线运行呢?

       老实讲,一般来说,桌面电脑的web应用程序即使能够完全离线运行也不能带来多大的好处,因为桌面电脑一般都是一直连线的。我特别期待看到的是,移动设备web应用程序能够从离线应用程序缓存技术得到多大的好处。

       在许多地方,移动电话普及率都在持续增长。如果能够自然地填补网络断线的鸿沟,移动设备浏览器中的web应用程序对用户来说就更加友好了。

       在一些特定场景中,使整个应用程序能够离线运行,意味着我们只需创建一个跨平台的浏览器解决方案,而不必创建多个内建应用程序。

       试想一下,一位销售员需要随时随地向她的顾客展示商品目录单。她可以使用任何她想要的电子设备,她首次浏览商品目录单时需要连线,之后便能够随时随地离线浏览。

       应用程序缓存技术并不只是在离线状态下才有用武之地。我们可以将应用程序缓存作为一个超级缓存,用于本地存储资源,这样可以加速应用程序启动。服务器上更新了的资源可以在后台线程重新加载,加载完成之后便替换掉本地旧的资源并更新到正在运行的应用程序上。这种方式非常适用于桌面电脑的重量级web应用程序。

       清单文件

       要使用应用程序缓存,你不需要编写大量代码。你可以在一个简单的文本文件中定义需要离线使用的资源,这个文件被称作清单(manifest)文件。

       清单文件格式

       一个简单的清单文件具有如下格式:

  1. CACHE MANIFEST
  2. # Version 1.0
  3. CACHE:
  4. /home/index
  5. /content/style.css
  6. /scripts/main.js
  7. NETWORK:
  8. /service/status
  9. FALLBACK:
  10. /logo.png /logo_offline.png
复制代码


       其中,你必须将CACHE MANIFEST 头放在清单文件的第一行。

       以数字符号#开头的行是注释行。这通常用于显式地修改清单文件以通知浏览器更新缓存。比如,在你更新了一张图片但没有修改图片的名称时,这种方式非常有用,因为浏览器并没有其他方式可以检测到服务器上的图片已被更新。

       接下来,清单文件包含了以下三节:CACHE,NETWORK以及FALLBACK。在CACHE节你可以指定需要缓存的资源。需要一直从服务器下载的资源(即使在断线的情况下)则在NETWORK中指定。如果有大量的资源需要一直从服务器下载,你可以在NETWORK节中使用通配字符(即一个星号*)表示。在FALLBACK节中,你可以指定在离线状态下可以使用的备用资源。

       清单文件的格式并不特别严格。以上介绍的几个部分可以是任意次序的,它们甚至可以在一个清单文件中多次使用。

       在清单文件中你可以使用相对路径或者绝对路径来定位资源。如果你使用相对路径,则必须以清单文件的位置作为参考来定位资源。

       引用清单文件

       要将清单文件绑定到应用程序,需要将manifest属性添加到html标签上。每个引用清单文件的页面自身默认会被缓存。然而,还是建议在清单文件中显示列出你想要缓存的资源。如果某个页面没有在清单文件中被指定,同时也不曾被在线浏览过,则在离线状态下无法访问到这个页面,因为浏览器无法知道页面是否存在于本地缓存中。

复制代码


       检查缓存状态

       使用应用程序缓存API,我们可以检查应用程序缓存的状态。使用window.applicationCache这个属性可以查询当前缓存的状态。该状态属性的值是一个介于0至5之间的数字,每个数字对应一个特定的缓存状态。

21.jpg


       你可以使用setInterval函数来快速显示状态变化。

  1. setInterval(function () {
  2.       console.log(window.applicationCache.status)
  3. }, 500);
复制代码


       事件处理

       除了检查缓存状态,我们还可以处理特定事件。

22.jpg


       缓存替换

       当新缓存下载完成之后,它并不会立即替换掉旧的缓存,而是直到我们通知应用程序使用新缓存时它才进行替换。我们可以通过处理updateready事件,使用swapCache将旧缓存替换为新缓存。更新的资源要在刷新页面后才能见到。

  1. window.applicationCache.onupdateready = function(){
  2.       window.applicationCache.swapCache();
  3. });
复制代码


       怎样让用户知道你的应用程序可以离线运行呢?

       据我所知,没有哪种浏览器会通知用户当前应用程序是能离线运行的。不过,我们可以自己通知用户:通过监听应用程序缓存的特定事件,当应用程序已经可以离线工作时通知用户。我们甚至可以将应用程序缓存生命周期的每个阶段都通知用户。

       应用程序缓存相关事件的处理是直截了当的。其中一个特别有用的事件是progress事件。每当一个资源下载完毕时这个事件被触发,其包含三个非常有用的属性,我们可以用这三个属性来显示下载进度:lengthComputable、loaded以及total。首先,我们需检查lengthComputable属性来判断loaded和total属性是否可用,接着我们使用loaded和total属性计算出资源下载的百分比进度。

  1. window.applicationCache.onchecking = function (e) {
  2.     updateCacheStatus('Checking for a new version of the application.');
  3. };
  4. window.applicationCache.ondownloading = function (e) {
  5.     updateCacheStatus('Downloading a new offline version of the application');
  6. };

  7. window.applicationCache.oncached = function (e) {
  8.     updateCacheStatus('The application is available offline.');
  9. };

  10. window.applicationCache.onerror = function (e) {
  11.     updateCacheStatus('Something went wrong while updating the offline version of the application. It will not be available offline.');
  12. };

  13. window.applicationCache.onupdateready = function (e) {
  14.     window.applicationCache.swapCache();
  15.     updateCacheStatus('The application was updated. Refresh for the changes to take place.');
  16. };

  17. window.applicationCache.onnoupdate = function (e) {
  18.     updateCacheStatus('The application is also available offline.');
  19. };

  20. window.applicationCache.onobsolete = function (e) {
  21.     updateCacheStatus('The application cannot be updated, no manifest file was found.');
  22. };

  23. window.applicationCache.onprogress = function (e) {
  24.     var message = 'Downloading offline resources.. ';
  25.     if (e.lengthComputable) {
  26.         updateCacheStatus(message + Math.round(e.loaded / e.total * 100) + '%');
  27.     } else {
  28.         updateCacheStatus(message);
  29.     };
  30. };
复制代码


       怎样检测浏览器是处于在线状态还是离线状态呢?

       你需要知道浏览器是在线的还是离线的有以下几个原因:也许是因为你想通知用户其正在离线工作,也许是因为你想在网络断开时禁用应用程序的某些功能,还或许是因为你想通过本地存储(local storage)技术以支持离线用户输入,然后在上线时将用户输入的文本同步到服务器。要实现这些需求,你可以通过自造基础架构,也可以通过使用开源项目或第三方项目。

       检测在线状态

       从原理上讲检测在线状态应该是非常简单的,比如在标准状况下,你使用navigator单件的onLine属性就可以检测出当前浏览器是否在线。

  1. console.log(navigator.onLine)
复制代码


       但事实上并非如此简单,因为各种浏览器对在线和离线的定义不尽相同。比如,旧版本的火狐浏览器只当用户显示地进行在线和离线状态切换时才更新onLine属性的值,而忽略了实际的网络状况。抛开实现上的不一致,检测网络连接状况本身就不是一件微不足道的事情。比如,假设你的电脑是连接上了的,但是你的路由器出问题了,这时应该显示什么状态呢?

       一种流行的hack方法是检查每个AJAX请求的状态码,然后当状态码为不成功时则回退到离线机制。

       事件处理

       如果你想在浏览器改变连线状态时做一些事情,你可以通过处理offline和online事件来实现。但是请注意,和检查onLine属性一样,使用这两个事件也有类似问题。

  1. window.addEventListener('offline', function(e) {
  2.   console.log('offline');
  3. }, false);
  4. window.addEventListener('online', function(e) {
  5.   alert('online');
  6. }, false);
复制代码


       浏览器支持

       除了Internet Explorer,所有主流现代浏览器都支持离线web应用程序。Internet Explorer 10也实现了相关规范,只是目前它还未发布。在caniuse.com上可以查看到每种浏览器及其版本对这一规范的支持情况。

       对于大部分实现,各主流浏览器基本上是相一致的。但在实现存储限额以及对限额的管理(这两项没有定义在规范中)上,各浏览器差异比较大。在测试你的web应用程序时应该考虑这个问题,移动设备中的浏览器在缓存大小上可是斤斤计较的。

       使用ASP.NET MVC生成和提供清单文件

       生成清单文件

       利用ASP.NET MVC创建和提供清单文件有几种方式。最简单地方式就是让ASP.NET MVC提供静态文本文件。然而,如果我们想要使用内建的ASP.NET MVC特性来解析路由,或者想编写代码来动态操控清单文件,我们最好使用自定义的action result。

       我把这个自定义的action result命名为ManifestResult,它继承自MVC框架中的FileResult类。提供清单文件服务时应该使用'text/cache-manifest' MIME类型,我把这个字符串传递给了父类的构造函数。

  1. public class ManifestResult : FileResult
  2. {
  3.     public ManifestResult(string version)
  4.         : base("text/cache-manifest") { }
  5. }
复制代码


       ManifestResult类具有四个属性,其中三个属性对应清单文件的三个节,另外一个属性对应版本号。表示CACHE节和NETWORK节的两个属性仅仅是字符串枚举,而表示FALLBACK节的属性是字典类型的,用于将资源映射到FALLBACK指定的资源。

  1. public class ManifestResult : FileResult
  2. {
  3.     public ManifestResult(string version)
  4.         : base("text/cache-manifest")
  5.     {
  6.             Version = version;
  7.         CacheResources = new List();
  8.         NetworkResources = new List();
  9.         FallbackResources = new Dictionary();
  10.     }
  11.     public string Version { get; set; }
  12.     public IEnumerable CacheResources { get; set; }
  13.     public IEnumerable NetworkResources { get; set; }
  14.     public Dictionary FallbackResources { get; set; }
  15. }
复制代码


       要将格式化的清单文件输出到响应流,需要重写WriteFile方法。

  1. protected override void WriteFile(HttpResponseBase response)
  2. {
  3. WriteManifestHeader(response);
  4.     WriteCacheResources(response);
  5.     WriteNetwork(response);
  6.     WriteFallback(response);
  7. }
  8. private void WriteManifestHeader(HttpResponseBase response)
  9. {
  10.     response.Output.WriteLine("CACHE MANIFEST");
  11.     response.Output.WriteLine("#V" + Version ?? string.Empty);
  12. }
  13. private void WriteCacheResources(HttpResponseBase response)
  14. {
  15.     response.Output.WriteLine("CACHE:");
  16.     foreach (var cacheResource in CacheResources)
  17.         response.Output.WriteLine(cacheResource);
  18. }
  19. private void WriteNetwork(HttpResponseBase response)
  20. {
  21.     response.Output.WriteLine();
  22.     response.Output.WriteLine("NETWORK:");
  23.     foreach (var networkResource in NetworkResources)
  24.         response.Output.WriteLine(networkResource);
  25. }
  26. private void WriteFallback(HttpResponseBase response)
  27. {
  28.     response.Output.WriteLine();
  29.     response.Output.WriteLine("FALLBACK:");
  30.     foreach (var fallbackResource in FallbackResources)
  31.         response.Output.WriteLine(fallbackResource.Key + " " + fallbackResource.Value);
  32. }
复制代码


       提供清单文件服务

       为了提供清单文件服务,我们要将相应的action添加到相应的控制器类中,以生成和返回清单文件的动作结果(action result)。在该action中,我们利用MVC的UrlHelper对象来正确地解析路由。

  1. public ActionResult Manifest()
  2. {
  3.      var manifestResult = new ManifestResult("1.0")
  4.     {
  5.          CacheResources = new List()
  6.              {
  7.                    Url.Action("Index", "Home"),
  8.                    "/content/style.css",
  9.                    "/scripts/main.js"
  10.              },
  11.              NetworkResources = new string[] { Url.Action("Status", "Service")},
  12.              FallbackResources = { { "/logo.png", "/logo_offline.png" } }
  13.     };
  14.     return manifestResult;
  15. }
复制代码


       为清单文件设置路由

       我们应该为清单文件设置特定的路由。大多数浏览器对清单文件的位置没有严格的规定,而最可靠的跨浏览器方式是将清单文件放在根目录,并将其命名为cache.manifest。在应用程序启动时,下面的代码将这个新的“cache.manifest”路由添加到路由表中。

  1. routes.MapRoute("cache.manifest", "cache.manifest", new { controller = "Resources", action = "Manifest" });
复制代码


       结论

       离线web应用程序是正处于不断发展中的HTML规范的重要内容之一。根据实际用例,你可能仅仅是利用这个特性来缓存资源或者让web应用程序完全离线运行。这个特性的中心就是清单文件。清单文件的格式和要求一点也不复杂,使用ASP.NET MVC或其他服务端技术可以直截了当地生成和提供清单文件服务。编写好清单文件之后,使用应用程序缓存API就可以很容易地进行缓存更新。你也可以使用这组API来查询缓存状态和处理应用程序缓存的特定事件。想知道浏览器处于在线状态还是离线状态,你可以通过检查navigator对象的onLine属性,或者处理特定的在线和离线事件来判断。


陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
如何將音頻添加到我的HTML5網站上?如何將音頻添加到我的HTML5網站上?Mar 10, 2025 pm 03:01 PM

本文解釋瞭如何使用< audio>元素,包括用於格式選擇的最佳實踐(MP3,OGG Vorbis),文件優化和JavaScript控件用於播放。 它強調使用多個音頻f

如何使用HTML5頁面可見性API檢測頁面何時可見?如何使用HTML5頁面可見性API檢測頁面何時可見?Mar 13, 2025 pm 07:51 PM

本文討論了使用HTML5頁面可見性API來檢測頁面可見性,提高用戶體驗並優化資源使用情況。關鍵方麵包括暫停媒體,減少CPU負載以及基於可見性變化管理分析。

如何使用視口元標記來控制移動設備上的頁面縮放?如何使用視口元標記來控制移動設備上的頁面縮放?Mar 13, 2025 pm 08:00 PM

本文討論了使用視口元標記來控制移動設備上的頁面縮放,重點是寬度和初始尺度之類的設置,以獲得最佳響應和性能。

如何將HTML5表單用於用戶輸入?如何將HTML5表單用於用戶輸入?Mar 10, 2025 pm 02:59 PM

本文解釋瞭如何創建和驗證HTML5表格。 它詳細介紹了>元素,輸入類型(文本,電子郵件,編號等)和屬性(必需,模式,最小,最大)。 HTML5的優勢比舊方法形成

如何使用地理位置API處理用戶位置隱私和權限?如何使用地理位置API處理用戶位置隱私和權限?Mar 18, 2025 pm 02:16 PM

本文討論了使用GeOlocation API管理用戶位置隱私和權限,並強調要求權限,確保數據安全性並遵守隱私法律的最佳實踐。

如何使用HTML5和JavaScript創建互動遊戲?如何使用HTML5和JavaScript創建互動遊戲?Mar 10, 2025 pm 06:34 PM

本文使用JavaScript詳細介紹了創建Interactive HTML5遊戲。 它涵蓋了遊戲設計,HTML結構,CSS樣式,JavaScript邏輯(包括事件處理和動畫)以及音頻集成。 必需的JavaScript庫(Phaser,Pi

如何將HTML5拖放API用於交互式用戶界面?如何將HTML5拖放API用於交互式用戶界面?Mar 18, 2025 pm 02:17 PM

本文介紹瞭如何使用HTML5拖放API來創建交互式用戶界面,詳細介紹了使元素可拖動的步驟,處理關鍵事件並通過自定義反饋來增強用戶體驗。它還討論了一個常見的陷阱

如何使用HTML5 Websockets API進行客戶端和服務器之間的雙向通信?如何使用HTML5 Websockets API進行客戶端和服務器之間的雙向通信?Mar 12, 2025 pm 03:20 PM

本文解釋了HTML5 Websockets API,用於實時雙向客戶服務器通信。 它詳細詳細介紹了客戶端(JavaScript)和服務器端(Python/Flask)的實現,以應對可伸縮性,狀態管理,一個挑戰

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前By尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。