写点什么

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:007331

评论

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

阿里P8现身说法,解密“架构”原理与实战笔记:从分布式到微服务

做梦都在改BUG

Java 架构 分布式 微服务

OpenHarmony 4.0 Beta1发布,邀您体验

OpenHarmony开发者

OpenHarmony

什么是双机热备技术?华为和思科如何实现双机热备?

做梦都在改BUG

Java 网络 双机热备

深入了解mock.js,打造出类似真实数据的模拟数据

Apifox

程序员 前端 前端开发 API Mock

用户组是什么意思?怎么容易理解?有什么作用?

行云管家

运维 权限 用户组

2022百度ESG报告发布:年度答卷展现安全信任承诺

百度安全

打造高可用的微服务架构:Spring Cloud 的优化与实践

xfgg

Java 微服务 SpringCloud 6 月 优质更文活动

浅谈微服务异步解决方案

做梦都在改BUG

Java 微服务 异步

Openjob 1.0.2 重磅发布,新一代分布式任务调度框架

stelin

分布式架构 Java 分布式

深度学习应用篇-计算机视觉-目标检测[4]:综述、边界框bounding box、锚框(Anchor box)、交并比、非极大值抑制NMS、SoftNMS

汀丶人工智能

人工智能 深度学习 计算机视觉 目标检测 6 月 优质更文活动

10分钟了解Kubernetes网络

俞凡

架构 Kubernetes 云原生

Amazon CodeWhisperer代码提示体验本文带你了解

我叫于豆豆吖.

云计算 亚马逊 亚马逊云

大厂面试必备!字节大佬刷Leetcode总结的算法笔记

做梦都在改BUG

Java 数据结构 算法 LeetCode

最强AIGC实战应用速成指南来了!14天掌握核心技术

飞桨PaddlePaddle

人工智能 深度学习 百度飞桨

探究核心技术&最佳实践,云原生OLAP论坛火热开启!

阿里云大数据AI技术

云原生

等待还是转行?GitHub爆赞的10W字Java八股文,你没得选择

做梦都在改BUG

Java java面试 Java八股文 Java面试题 Java面试八股文

百度离线资源治理

百度Geek说

数据库 大数据 离线 企业号 6 月 PK 榜 6 月 优质更文活动

来了解Amazon CodeWhisperer的强大吧

初学者

云计算 亚马逊 亚马逊云

深度学习应用篇-计算机视觉-图像分类[3]:ResNeXt、Res2Net、Swin Transformer、Vision Transformer等模型结构、实现、模型特点详细介绍

汀丶人工智能

人工智能 深度学习 计算机视觉 图像分类 6 月 优质更文活动

问道价值互联网,区块链的下一个十年 | 2023开放原子全球开源峰会区块链分论坛即将启幕

开放原子开源基金会

区块链 开源 开放原子全球开源峰会

2023世界人工智能大会“AI生成与垂直大语言模型”论坛重磅来袭!

NLP资深玩家

深入探究Flink:实时处理与批量处理的完美结合

xfgg

Java flink 6 月 优质更文活动

瞄准“量效”难题,百度营销创新推出大健康线索营销解决方案-医效通

说山水

赋能生态合作 共话数字创新 | 2023开放原子全球开源峰会软硬协同开源分论坛即将启幕

开放原子开源基金会

开源 开放原子全球开源峰会 开放原子 软硬协同开源

咸阳有没有等保测评机构?在哪里?怎么联系?

行云管家

等保 等保测评 等保测评机构 咸阳

AI老师的作者:17岁的高中生,可能是你想要孩子成为的样子

无人之路

AI 教育 ChatGPT

来自大佬的洗礼!全网独家的SpringBoot核心文档,讲的太清晰了

做梦都在改BUG

Java Spring Boot

Jogger慢跑者链游系统开发NFT技术

薇電13242772558

NFT 链游

“变脸的秘密”!直播源码app开发技术特效功能的实现

山东布谷科技

源码剖析 APP开发 软件开发、 源码搭建 直播源码

【体验有奖】玩转 AIGC,函数计算 x 通义千问预体验,一键部署AI应用赢Airpods

Serverless Devs

函数计算FC AIGC

让ChatGPT来写今年的高考作文,能得几分?

楚少AI

ChatGPT4 2023高考 ChatGPT写作

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