BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

Dojo1.6新特性:HTML5进行时

| 作者 钟思奇 关注 0 他的粉丝 发布于 2011年4月23日. 估计阅读时间: 22 分钟 | GMTC大前端的下一站,PWA、Web框架、Node等最新最热的大前端话题邀你一起共同探讨。

近年来HTML5的关注度越来越高。虽然该规范还在紧锣密鼓地制定中,但是相信很多HTML5的概念大家已经耳熟能详,如具有强大绘图功能的canvas、有望替代Flash播放器的视频(vedio)音频(audio)标签、得到增强的各种表单元素、为提供大数据存储而设计的Web Storage、统一的标签自定义属性设计、内置的元素拖拽功能等。这些新特性无疑将为用户带来更酷的用户体验,同时也将为广大Web开发者提供更广阔的平台。

Dojo作为最老牌的JavaScript库之一,近年来也一直没有停止过对各种新技术的应用,对新标准的融合。也许你已经使用dojo很久,但可曾注意过dojo中对HTML5的应用呢?本文将就此为大家介绍一些Dojo中已经用到的HTML5特性!

  • 支持HTML5 自定义属性的dojo.parser
  • 支持HTML Canvas的dojox.gfx和dojox.charting
  • 支持HTML5 indexed Database Object Store API 的 dojo.store API
  • 基于HTML5 localstorage的dojox.storage.LocalStorageProvider
  • 支持HTML5 multiple file input 的 dojox.form.Uploader

支持HTML5 自定义属性的dojo.parser

如何为页面中的一个节点设置一个自定义属性来判断该节点是否可以被拖拽?面对这个问题,我们可能会不假思索地为节点附上一个“draggable”属性。但我们往往忽略了一点——这个“draggable”属性是否会与别的属性发生冲突?我们的经验告诉我们不会。的确,在HTML5之前,我们往往会通过这种方式来实现拖拽功能。但不幸的是,在HTML5中,“draggbale”已经是标准属性之一,这也就意味着修改“draggable”属性会修改节点对应的浏览器行为,而这并不一定是你想要的。

其实在dojo1.5之前的版本中,我们就一直在使用这种可能存在风险的自定义属性。回想一下我们是如何用标签声明一个常用的dojo按钮控件dijit.form.Button的:

<button id="button1" dojoType="dijit.form.Button">Button1</button>

虽说dojoType并不太可能成为HTML标准属性之一,但不可否认这不是一种优雅的实现方式。

而HTML5中已经有了针对自定义属性的规范。所有自定义属性都必须以data-作为前缀。这样就可以很方便的将HTML标准属性与自定义属性区分开来,不仅提供了代码的可读性也避免了与标准属性冲突的风险。

在dojo1.6中,也针对HTML5的这一规范做出了相应的改进。你可以在dojo1.6中发现一系列符合标准的自定义属性,这些属性已经可以被dojo.parser正确地识别出来: 

  • data-dojo-config:取代了原来的dojoConfig,用以配置dojo库的各项参数
  • data-dojo-type:取代了原来的dojoType属性,用以指定所用的dojo对象类型
  • data-dojo-props:取代了原来所有初始化dojo控件的自定义属性。

其中data-dojo-config与data-dojo-type的使用方法与原来的dojoConfig以及dojoType没有区别。而data-dojo-props则大大美化了初始化控件时的属性配置代码。

使用非HTML5标准属性时,声明一个简单的CheckBox我们可能需要为节点单独设置5个属性值: 

<input name="cb1" id="cb1" value="foo" 
    dojoType="dijit.form.CheckBox" 
    onClick="console.log('clicked cb1')">

而在使用HTML5标准属性data-dojo-props之后,我们则只需要设置三个属性:

<input id="cb1" data-dojo-id="cb1" data-dojo-type="dijit.form.CheckBox" 
    data-dojo-props='name:"cb1", value:"foo", 
    onClick:function(){ console.log("clicked cb1") }'/> 

更值得注意是,这样的声明方法和使用JavaScript动态创建一个CheckBox非常相似:

new dijit.form.CheckBox({
id: "cb1",
name: "cb1",
value: "foo",
onclick: function(){console.log("clicked cb1")},
}, "cb1");

这是因为dojo.parser会将data-dojo-props中的内容作为一个散列参数表来初始化控件。这使得标签和代码两种形式的初始化代码可以最大程度上的保持一致。

可见,HTML5的自定义属性在dojo中得到了充分的利用,带来了很好的效果。不过在dojo1.6中,这样的自定义属性还不能使用在dojox.mobile包中的控件上。不过可以预见,在以后的版本中,dojox.mobile包中的控件也将支持这一实用的特性。

支持HTML Canvas的dojox.gfx和dojox.charting

在HTML5众多特性之中,Canvas可能是带给大家感受最深的一个了。众多基于Canvas的应用充分展示了它强大的绘图功能。其基本绘图流程如下:

// 获取canvas元素
var canvasElement= document.getElementById("canvas");
// 默认浏览器支持Canvas,获取canvas元素对应的2D上下文环境
var canvasContext = canvasElement.getContext("2d");
If(canvasContext){
    canvasContext.fillStyle = "#1433FF"; //设置绘图的填充色
    canvasContext.strokeStyle = "#FF1500"; //设置绘图的线条显色
    canvasContext.lineWidth = 1; //设置绘图的线条宽度
    canvasContext.fillRect (10, 10, 110, 110); //绘制实心矩形
    canvasContext.strokeRect(10, 230, 110, 110); //绘制空心矩形
}

此外canvasContext还提供了功能齐全的绘制折线、文字、阴影、图片等API。这些内容已远远超过本文所涉及的范围,因此不再一一赘述。

对于如此强大的Canvas,dojo其实也早已经将其整合到了自己的图形模块中。由于dojox.gfx包下的dojox.gfx.canvas模块对 HTML5 Canvas API的绘图接口进行了封装,使得dojox.gfx的canvas绘图接口VML、SilverLight绘图没有任何区别。你不需要任何的 Canvas API使用经验,只需在dojo的配置选项中将图形渲染模式设置为canvas即可:

<script type="text/javascript" data-dojo-config="gfxRenderer:'canvas'"  src="dojo.js"></script>

借助于dojox.gfx对于各种绘图方式一直的接口,dojox.charting下的所有图表也都支持canvas模式。只需将渲染模式设置为canvas,你便获得了一套完全基于HTML5 Canvas API的图表库。

此外,你还可以通过为gfxRenderer配置候补选项来使dojox.gfx在不支持HTML5的环境下自动使用其他渲染器。如下列代码就指定优先使用HTML5 Canvas进行图形渲染,如果浏览器不支持canvas的话会依次尝试svg和vml进行渲染。

<script type="text/javascript" data-dojo-config="gfxRenderer:'canvas,svg,vml'"  
    src="dojo.js"></script>

支持HTML5 indexed Database Object Store API 的 dojo.store API

在HTML5中提出了一套基于键值对的数据存储API。使用者可以简单透明地通过使用以下方法来对存储的数据进行查询、更新、添加、删除:

  • get(index): 根据索引值获取数据。
  • put(value, /*可选*/ index): 更新数据记录。
  • add(value,/*可选*/ index): 添加数据记录。若索引指向位置已存在记录,则添加失败。
  • remove(index): 根据索引值移除数据记录。

dojo 1.6中的dojo.store很好的实现了这一套接口,更加简化了原有的dojo.data包所提供的数据存储API。dojo.store包下有三种已实现的store:

  • Memory:简单、轻量级的store,适合处理小数据集。
  • JsonRest:专门为REST API服务的store,适合处理大数据集。
  • DataStore:用于为原有dojo.data包下的store提供object store api的store

这三种store虽然初始化方法和使用场景各有不同,但都提供了符合HTML5标准的get,put,remove方法(除了DataStore之外,也都提供了add方法)。用户可以通过如下的流程对这些store进行很方便的操作:

//获取索引为some-id的记录
var record =  store.get("some-id");
//修改获取的记录的bar字段
record.bar = newValue;
//更新该记录
store.put(record);
//创建一条新记录
var newRecord = {id: "some-new-id", 
    bar: "bar",
    foo: "foo"
};
Store.add(newRecord );

我们可以看到使用dojo.store包实现的object store API进行数据管理就如同管理普通JavaScript Object一样方便。之后我们还将看到这套API还完美的应用到了dojo对于HTML5 localstorage的实现——dojox.storage.LocalStoragePovider上。

基于HTML5 localstorage的dojox.storage.LocalStorageProvider

HTML5 在数据存储方面不仅仅提供了方便的indexed Database Object Store API,还提供了十分有用的Local Storage。 Local Storage也被称作Web Storage、Dom Storage。简单地说其本质就是以键值对保存的Web页面信息。和以前我们常用的cookies一样,可以保存页面相关信息,哪怕用户离开当前页面甚至直接关闭了浏览器。相较于cookies,Local Storage最大的特点就是可以储存更多的信息——cookies最大只能保存4KB数据。同时Local Storage中的数据并不会被传递到服务器端(cookies则会随着http请求被发送)。

LocalStorage的使用方法也十分简便,从LocalStorage获取一个值可以通过

var value = localstorage.getItem("bar");

或更加简便的

localstorage["bar"];

方式获得。

而向localstorage写一个值可以通过

localstorage.setItem("bar", "newValue");

或更加简便的

localstorage["bar"] = "newValue";

来实现。

dojo 的dojox.storage 包提供了各类常用的数据存储工具:适用于cookies的CookieStorageProvider,适用于Google gears的GearsStorageProvider,适用于Adobe Air的AirDBStorageProvider、AireFileStorageProvider、 AireEncryptedLocalStorageProvider等。

其中dojo也专门针对HTML5 local storage特性提供了LocalStorageProvider。

LocalStorageProvider完全兼容简便的Object Store API,其接口及其主要功能如下:

put: function( /*string*/ key, /*object*/ value, /*function*/ resultsHandler,/*string?*/ namespace)

用以保存一对键值。第一个参数为所要保存的数据的索引。第二个参数是所要保存的数据。第三个参数用以处理数据保存结果的回调函数(数据保存可能失败)。最后一个参数为可选的命名空间名。dojo为了更好的管理存储内容,提供了命名空间这一参数,其本质是将命名空间和索引组成一个形为 “__namespace_key”的新索引值,而命名空间的默认值为“default”。

get: function(/*string*/ key, /*string?*/ namespace)

用以获取指定命名空间下的所给索引指向的数据。

第一个参数为所要获取的数据的索引。第二个参数为可选的命名空间名,默认值为“default”。

remove: function(/*string*/ key, /*string?*/ namespace)

用以删除指定命名空间下的所给索引指向的数据

第一个参数为所要获取的数据的索引。第二个参数为可选的命名空间名,默认值为“default”。

clear: function(/*string?*/ namespace)

用以清空指定命名空间下的所有数据。参数为可选的命名空间名,默认值为“default”。

这些API不仅仅与dojox.storage包下的其余provider保持一致,还与dojo.store包中提供的store对象的接口兼容。因此 dojox.storage.LocalStorageProvider和dojo.store包为HTML5的存储体系提供了完整的支持。

支持HTML5 multiple file input 的 dojox.form.Uploader

HTML5 中对各种标签都进行了增强,其中也不乏对于各类HTML控件的改进。其中input标签就获得了名为multiple的新属性。以前HTML中的 input标签只能选择单个文件,而有了multiple属性之后,你可以使用input标签一次性选择多个文件。如有一个input控件:

<input multiple="multiple" id="uploadfile" type="file" name="uploaddfile"></div>

你可以点击浏览按钮之后在文件选择窗口中一次性选择多个需要的文件。并且可以通过如下代码获取选择的文件信息:

var files = document.getElementById("uploadfile").files;

input标签的文件选择功能往往被应用于文件的上传中。而dojo 1.6中的dojox.form.uploader则很好的利用了HTML5这一新特性实现了基于HTML5的多文件上传。

首先dojox.form.Uploader会判断当前的浏览器是否支持HTML5的增强版input标签,如果支持,那么dojox.form.Uploader将会使用带有multiple属性的input标签。

dojx.form.Uploader提供了以下API对HTML5的多文件上传进行支持:

getFileList: function()

用以获取当前选择的文件信息。本质是获取对应的input标签下的files数据进行整理,并为每个文件添加索引。

upload: function(/*Object ? */formData)

用以上传指定数据(文件),dojox.form.uploader.plugins.HTML5具体实现了该方法的HTML5版本(还有Flash和 Iframe两种版本可选,分别由其余两个插件实现)。该方法会判断当前的浏览器是否支持FormData(Firefox 4以上和Webkit内核的浏览器基本都支持),若支持则使用该方式上传,否则使用binary格式上传。

submit: function(/* form Node ? */form)

用于当dojox.form.Uploader处于一个form表单之中时,同时上传文件及表单内其他信息。

reset: function()

用以清除当前选择的所有文件,还不支持清除单个指定的文件。

有了dojox.form.Uploader,你可以很方便的创建一个基于HTML5的多文件上传控件,并使用其API对其进行控制。当然,dojo也为不支持HTML5这一新特性的浏览器提供了其他解决方案。你可以发现在dojox.form.uploader.plugins包下除了HTML5之外还有 IFrame和Flash两种插件。如果浏览器不支持HTML5的多文件选择功能,那么dojox.form.Uploader会自动尝试使用这两个插件来实现多文件上传。你无需为了让代码可以跨平台而花费任何精力。

总结

现在我们可以发现,在Dojo中,HTML5其实早已应用在各个方面,从数据存储到图形绘制,从代码风格到具体控件。相信在将来的版本中,Dojo会一如既往的融入各种新技术、兼容各种新标准,提供更好的用户体验!

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

好文章 by Song Hanson

不过等Dojo出1.7了再上1.6,没必要吃螃蟹。另,“但不可否认这不是一种优雅的实现方式”这句话很费解啊。

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

1 讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT