【ArchSummit架构师峰会】探讨数据与人工智能相互驱动的关系>>> 了解详情
写点什么

Dojo1.6 新特性:HTML5 进行时

  • 2011-04-22
  • 本文字数:5451 字

    阅读完需:约 18 分钟

近年来 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 会一如既往的融入各种新技术、兼容各种新标准,提供更好的用户体验!

2011-04-22 00:006872

评论

发布
暂无评论
发现更多内容

令人头秃的js隐式转换面试题,你能做对吗

loveX001

JavaScript

Collections之Arraylist源码解读(五)

知识浅谈

ArrayList 10月月更

JDK源码对你最有触动的是哪一段#集合

琦彦

Java 集合 10月月更

【LeetCode】子域名访问计数Java题解

Albert

LeetCode 10月月更

2022-10-04:以下go语言代码输出什么?A:{123} main.T{x:123} B:{123} T{x:123} C:boo boo D:boo main.T{x:123}。 packag

福大大架构师每日一题

golang 福大大 选择题

Spring 测试运行的时候提示 Unable to find a @SpringBootConfiguration 错误

HoneyMoose

React-Hooks怎样封装防抖和节流-面试真题

beifeng1996

React

面试官:React怎么做性能优化

beifeng1996

React

说说你对Vue的keep-alive的理解

bb_xiaxia1998

Vue

黄山归来不看岳:《Java开发手册(黄山版)》新增 11 条规约

琦彦

Java Java开发手册 10月月更

JDK源码对你最有触动的是哪一段#HashMap

琦彦

Java hashmap 10月月更

通过单步调试的方式学习 Angular 中 TView 和 LView 的概念

Jerry Wang

typescript 前端开发 angular 10月月更 前端开发web开发

80%的前端开发都答不上来的js异步面试题

loveX001

JavaScript

【一Go到底】第五天---指针

指剑

Go golang 10月月更

Fiddler(一) - Fiddler简介

No Silver Bullet

fiddler 10月月更 抓包工具

说说Vue响应式系统中的Watcher和Dep的关系-面试进阶

bb_xiaxia1998

Vue

Vue3入门指北(九)生命周期钩子

Augus

Vue3 10月月更

什么是 Python 垃圾回收机制中的引用计数

宇宙之一粟

Python 垃圾回收机制 引用计数 10月月更

假如面试官要你手写一个promise

helloworld1024fd

JavaScript

Fiddler(二) - 使用Fiddler做抓包分析

No Silver Bullet

fiddler 抓包分析 10月月更

微服务通信

穿过生命散发芬芳

微服务 10月月更

不懂FAQ页面怎么设计?一些产品FAQ页面模板展示!

Baklib

产品 FAQ

网络请求模块(2)

张立梵

Python. 爬虫必备知识讲解 10月月更

手写JS函数的call、apply、bind

helloworld1024fd

JavaScript

手写节流防抖函数

helloworld1024fd

JavaScript

C++学习---cstdio的源码学习分析05-打开文件函数fopen

桑榆

c++ 源码分析 10月月更

老生常谈React的diff算法原理-面试版

beifeng1996

React

Mac下vagrant从安装到体验

程序员欣宸

vagrant 虚拟机 10月月更

Vue是怎样监听数组的变化的?

bb_xiaxia1998

Vue

大数据ELK(十三):Elasticsearch编程(添加职位数据)

Lansonli

10月月更

经常会采坑的javascript原型应试题

loveX001

JavaScript

Dojo1.6新特性:HTML5进行时_Java_钟思奇_InfoQ精选文章