Web应用中的离线数据存储

Web应用中的离线数据存储

2014/02/15 · HTML5,
JavaScript ·
HTML5,
Javascript

本文由 伯乐在线
njuyz
翻译。未经许可,禁止转载!
英文出处:Nettuts+。欢迎加入翻译组

为了提升Web应用的用户体验,想必很多开发者都会项目中引入离线数据存储机制。可是面对各种各样的离线数据技术,哪一种才是最能满足项目需求的呢?本文将帮助各位找到最合适的那一个。

本文由 伯乐在线
njuyz
翻译。未经许可,禁止转载!
英文出处:Nettuts+。欢迎加入翻译组

引言

随着HTML5的到来,各种Web离线数据技术进入了开发人员的视野。诸如AppCache、localStorage、sessionStorage和IndexedDB等等,每一种技术都有它们各自适用的范畴。比如AppCache就比较适合用于离线起动应用,或者在离线状态下使应用的一部分功能照常运行。接下来我将会为大家作详细介绍,并且用一些代码片段来展示如何使用这些技术。

为了提升Web应用的用户体验,想必很多开发者都会项目中引入离线数据存储机制。可是面对各种各样的离线数据技术,哪一种才是最能满足项目需求的呢?本文将帮助各位找到最合适的那一个。

AppCache

如果你的Web应用中有一部分功能(或者整个应用)需要在脱离服务器的情况下使用,那么就可以通过AppCache来让你的用户在离线状态下也能使用。你所需要做的就是创建一个配置文件,在其中指定哪些资源需要被缓存,哪些不需要。此外,还能在其中指定某些联机资源在脱机条件下的替代资源。

AppCache的配置文件通常是一个以.appcache结尾的文本文件(推荐写法)。文件以CACHE MANIFEST开头,包含下列三部分内容:

  • CACHE – 指定了哪些资源在用户第一次访问站点的时候需要被下载并缓存
  • NETWORK
    指定了哪些资源需要在联机条件下才能访问,这些资源从不被缓存
  • FALLBACK – 指定了上述资源在脱机条件下的替代资源

引言

随着HTML5的到来,各种Web离线数据技术进入了开发人员的视野。诸如AppCache、localStorage、sessionStorage和IndexedDB等等,每一种技术都有它们各自适用的范畴。比如AppCache就比较适合用于离线起动应用,或者在离线状态下使应用的一部分功能照常运行。接下来我将会为大家作详细介绍,并且用一些代码片段来展示如何使用这些技术。

示例

首先,你需要在页面上指定AppCache的配置文件:

XHTML

<!DOCTYPE html> <html manifest=”manifest.appcache”> …
</html>

1
2
3
4
<!DOCTYPE html>
<html manifest="manifest.appcache">
</html>

在这里千万记得在服务器端发布上述配置文件的时候,需要将MIME类型设置为text/cache-manifest,否则浏览器无法正常解析。

接下来是创建之前定义好的各种资源。我们假定在这个示例中,你开发的是一个交互类站点,用户可以在上面联系别人并且发表评论。用户在离线的状态下依然可以访问网站的静态部分,而联系以及发表评论的页面则会被其它页面替代,无法访问。

好的,我们这就着手定义那些静态资源:

JavaScript

CACHE MANIFEST CACHE: /about.html /portfolio.html
/portfolio_gallery/image_1.jpg /portfolio_gallery/image_2.jpg
/info.html /style.css /main.js /jquery.min.js

1
2
3
4
5
6
7
8
9
10
11
CACHE MANIFEST
 
CACHE:
/about.html
/portfolio.html
/portfolio_gallery/image_1.jpg
/portfolio_gallery/image_2.jpg
/info.html
/style.css
/main.js
/jquery.min.js

旁注:配置文件写起来有一点很不方便。举例来说,如果你想缓存整个目录,你不能直接在CACHE部分使用通配符(*),而是只能在NETWORK部分使用通配符把所有不应该被缓存的资源写出来。

你不需要显式地缓存包含配置文件的页面,因为这个页面会自动被缓存。接下来我们为联系和评论的页面定义FALLBACK部分:

JavaScript

FALLBACK: /contact.html /offline.html /comments.html /offline.html

1
2
3
FALLBACK:
/contact.html /offline.html
/comments.html /offline.html

最后我们用一个通配符来阻止其余的资源被缓存:

JavaScript

NETWORK: *

1
2
NETWORK:
*

最后的结果就是下面这样:

JavaScript

CACHE MANIFEST CACHE: /about.html /portfolio.html
/portfolio_gallery/image_1.jpg /portfolio_gallery/image_2.jpg
/info.html /style.css /main.js /jquery.min.js FALLBACK: /contact.html
/offline.html /comments.html /offline.html NETWORK: *

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CACHE MANIFEST
 
CACHE:
/about.html
/portfolio.html
/portfolio_gallery/image_1.jpg
/portfolio_gallery/image_2.jpg
/info.html
/style.css
/main.js
/jquery.min.js
 
FALLBACK:
/contact.html /offline.html
/comments.html /offline.html
 
NETWORK:
*

还有一件很重要的事情要记得:你的资源只会被缓存一次!也就是说,如果资源更新了,它们不会自动更新,除非你修改了配置文件。所以有一个最佳实践是,在配置文件中增加一项版本号,每次更新资源的时候顺带更新版本号:

JavaScript

CACHE MANIFEST # version 1 CACHE: …

1
2
3
4
5
6
CACHE MANIFEST
 
# version 1
 
CACHE:

AppCache

如果你的Web应用中有一部分功能(或者整个应用)需要在脱离服务器的情况下使用,那么就可以通过AppCache来让你的用户在离线状态下也能使用。你所需要做的就是创建一个配置文件,在其中指定哪些资源需要被缓存,哪些不需要。此外,还能在其中指定某些联机资源在脱机条件下的替代资源。

AppCache的配置文件通常是一个以.appcache结尾的文本文件(推荐写法)。文件以CACHE MANIFEST开头,包含下列三部分内容:

  • CACHE – 指定了哪些资源在用户第一次访问站点的时候需要被下载并缓存
  • NETWORK
    指定了哪些资源需要在联机条件下才能访问,这些资源从不被缓存
  • FALLBACK – 指定了上述资源在脱机条件下的替代资源

LocalStorage和SessionStorage

如果你想在Javascript代码里面保存些数据,那么这两个东西就派上用场了。前一个可以保存数据,永远不会过期(expire)。只要是相同的域和端口,所有的页面中都能访问到通过LocalStorage保存的数据。举个简单的例子,你可以用它来保存用户设置,用户可以把他的个人喜好保存在当前使用的电脑上,以后打开应用的时候能够直接加载。后者也能保存数据,但是一旦关闭浏览器窗口(译者注:浏览器窗口,window,如果是多tab浏览器,则此处指代tab)就失效了。而且这些数据不能在不同的浏览器窗口之间共享,即使是在不同的窗口中访问同一个Web应用的其它页面。

旁注:有一点需要提醒的是,LocalStorage和SessionStorage里面只能保存基本类型的数据,也就是字符串和数字类型。其它所有的数据可以通过各自的toString()方法转化后保存。如果你想保存一个对象,则需要使用JSON.stringfy方法。(如果这个对象是一个类,你可以复写它默认的toString()方法,这个方法会自动被调用)。

示例

首先,你需要在页面上指定AppCache的配置文件:

XHTML

<!DOCTYPE html> <html manifest=”manifest.appcache”> …
</html>

1
2
3
4
<!DOCTYPE html>
<html manifest="manifest.appcache">
</html>

在这里千万记得在服务器端发布上述配置文件的时候,需要将MIME类型设置为text/cache-manifest,否则浏览器无法正常解析。

接下来是创建之前定义好的各种资源。我们假定在这个示例中,你开发的是一个交互类站点,用户可以在上面联系别人并且发表评论。用户在离线的状态下依然可以访问网站的静态部分,而联系以及发表评论的页面则会被其它页面替代,无法访问。

好的,我们这就着手定义那些静态资源:

JavaScript

CACHE MANIFEST CACHE: /about.html /portfolio.html
/portfolio_gallery/image_1.jpg /portfolio_gallery/image_2.jpg
/info.html /style.css /main.js /jquery.min.js

1
2
3
4
5
6
7
8
9
10
11
CACHE MANIFEST
 
CACHE:
/about.html
/portfolio.html
/portfolio_gallery/image_1.jpg
/portfolio_gallery/image_2.jpg
/info.html
/style.css
/main.js
/jquery.min.js

旁注:配置文件写起来有一点很不方便。举例来说,如果你想缓存整个目录,你不能直接在CACHE部分使用通配符(*),而是只能在NETWORK部分使用通配符把所有不应该被缓存的资源写出来。

你不需要显式地缓存包含配置文件的页面,因为这个页面会自动被缓存。接下来我们为联系和评论的页面定义FALLBACK部分:

JavaScript

FALLBACK: /contact.html /offline.html /comments.html /offline.html

1
2
3
FALLBACK:
/contact.html /offline.html
/comments.html /offline.html

最后我们用一个通配符来阻止其余的资源被缓存:

JavaScript

NETWORK: *

1
2
NETWORK:
*

最后的结果就是下面这样:

JavaScript

CACHE MANIFEST CACHE: /about.html /portfolio.html
/portfolio_gallery/image_1.jpg /portfolio_gallery/image_2.jpg
/info.html /style.css /main.js /jquery.min.js FALLBACK: /contact.html
/offline.html /comments.html /offline.html NETWORK: *

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CACHE MANIFEST
 
CACHE:
/about.html
/portfolio.html
/portfolio_gallery/image_1.jpg
/portfolio_gallery/image_2.jpg
/info.html
/style.css
/main.js
/jquery.min.js
 
FALLBACK:
/contact.html /offline.html
/comments.html /offline.html
 
NETWORK:
*

还有一件很重要的事情要记得:你的资源只会被缓存一次!也就是说,如果资源更新了,它们不会自动更新,除非你修改了配置文件。所以有一个最佳实践是,在配置文件中增加一项版本号,每次更新资源的时候顺带更新版本号:

JavaScript

CACHE MANIFEST # version 1 CACHE: …

1
2
3
4
5
6
CACHE MANIFEST
 
# version 1
 
CACHE:

示例

我们不妨来看看之前的例子。在联系人和评论的部分,我们可以随时保存用户输入的东西。这样一来,即使用户不小心关闭了浏览器,之前输入的东西也不会丢失。对于jQuery来说,这个功能是小菜一碟。(注意:表单中每个输入字段都有id,在这里我们就用id来指代具体的字段)

JavaScript

$(‘#comments-input, .contact-field’).on(‘keyup’, function () { // let’s
check if localStorage is supported if (window.localStorage) {
localStorage.setItem($(this).attr(‘id’), $(this).val()); } });

1
2
3
4
5
6
$(‘#comments-input, .contact-field’).on(‘keyup’, function () {
   // let’s check if localStorage is supported
   if (window.localStorage) {
      localStorage.setItem($(this).attr(‘id’), $(this).val());
   }
});

每次提交联系人和评论的表单,我们需要清空缓存的值,我们可以这样处理提交(submit)事件:

JavaScript

$(‘#comments-form, #contact-form’).on(‘submit’, function () { // get
all of the fields we saved $(‘#comments-input,
.contact-field’).each(function () { // get field’s id and remove it from
local storage localStorage.removeItem($(this).attr(‘id’)); }); });

1
2
3
4
5
6
7
$(‘#comments-form, #contact-form’).on(‘submit’, function () {
   // get all of the fields we saved
   $(‘#comments-input, .contact-field’).each(function () {
      // get field’s id and remove it from local storage
      localStorage.removeItem($(this).attr(‘id’));
   });
});

最后,每次加载页面的时候,把缓存的值填充到表单上即可:

JavaScript

// get all of the fields we saved $(‘#comments-input,
.contact-field’).each(function () { // get field’s id and get it’s value
from local storage var val = localStorage.getItem($(this).attr(‘id’));
// if the value exists, set it if (val) { $(this).val(val); } });

1
2
3
4
5
6
7
8
9
// get all of the fields we saved
$(‘#comments-input, .contact-field’).each(function () {
   // get field’s id and get it’s value from local storage
   var val = localStorage.getItem($(this).attr(‘id’));
   // if the value exists, set it
   if (val) {
      $(this).val(val);
   }
});

LocalStorage和SessionStorage

如果你想在Javascript代码里面保存些数据,那么这两个东西就派上用场了。前一个可以保存数据,永远不会过期(expire)。只要是相同的域和端口,所有的页面中都能访问到通过LocalStorage保存的数据。举个简单的例子,你可以用它来保存用户设置,用户可以把他的个人喜好保存在当前使用的电脑上,以后打开应用的时候能够直接加载。后者也能保存数据,但是一旦关闭浏览器窗口(译者注:浏览器窗口,window,如果是多tab浏览器,则此处指代tab)就失效了。而且这些数据不能在不同的浏览器窗口之间共享,即使是在不同的窗口中访问同一个Web应用的其它页面。

旁注:有一点需要提醒的是,LocalStorage和SessionStorage里面只能保存基本类型的数据,也就是字符串和数字类型。其它所有的数据可以通过各自的toString()方法转化后保存。如果你想保存一个对象,则需要使用JSON.stringfy方法。(如果这个对象是一个类,你可以复写它默认的toString()方法,这个方法会自动被调用)。

相关文章