HT for Web的HTML5树组件有延迟加载的功能,这个功能对于那些需要从服务器读取具有层级依赖关系数据时非常有用,需要获取数据的时候再向服务器发起请求,这样可减轻服务器压力,同时也减少了浏览器的等待时间,让页面的加载更加流畅,增强用户体验。
进入正题,今天用来做演示的Demo是,客户端请求服务器读取系统文件目录结构,通过HT for Web的HTML5树组件显示系统文件目录结构。
首先,我们先来设计下服务器,这次Demo的服务器采用Node.js,用到了Node.js的express、socket.io、fs和http这四个模块,Node.js的相关知识,我在这里就不阐述了,网上的教材一堆,这里推荐下socket.io的相关入门http://socket.io/get-started/chat/。
服务端代码代码:

var fs = require('fs'),express = require('express'),app = express(),server = require('http').createServer(app),io = require('socket.io')(server),root = ‘/Users/admin/Projects/ht-for-web/guide‘;io.on('connection', function(socket){socket.on('explore', function(url){socket.emit('file', walk(url || root));});
});app.use(express.static('/Users/admin/Projects/ht-for-web'));server.listen(5000, function(){console.log('server is listening at port 5000');
});

io监听了connection事件,并获得一个socket;socket再监听一个叫explore的自定义事件,通过url参数获取到数据后,派发一个叫file的自定义事件,供客户端监听并做相应处理;通过app.use结合express.static设置项目路径;最后让server监听5000端口。
到此,一个简单的服务器就搭建好了,现在可以通过http://localhost:5000来访问服务器了。等等,好像缺了点什么。对了,获取系统文件目录结构的方法忘记给了,OK,那么我们就先来看看获取整站文件的代码是怎么写的:

function walk(pa) {var dirList = fs.readdirSync(pa),key = pa.substring(pa.lastIndexOf('/') + 1),obj = {name: key,path: pa,children: [],files: []};dirList.forEach(function(item) {var stats = fs.statSync(pa + '/' + item);if (stats.isDirectory()) {obj.children.push(walk(pa + '/' + item));}else {obj.files.push({name: item, dir: pa + '/' + item});}});return obj;
}

如大家所见,采用递归的方式,逐层遍历子目录,代码也没什么高深的地方,相信大家都看得懂。那我们来看看运行效果吧:

duang~文件目录结构出来了,是不是感觉酷酷的,这代码量不小吧。其实,代码并不多,贴出来大家瞅瞅:

<!DOCTYPE html>
<html>
<head lang="en"><meta charset="UTF-8"><title>tree-loader</title><script src="/socket.io/socket.io.js"></script><script src="/lib/core/ht.js"></script><script>var socket = io(), idMap = {};function init() {var dm = window.dm = new ht.DataModel(),tree = new ht.widget.TreeView(dm);tree.addToDOM();socket.on('file', function(data) {var root = dm.getDataById(idMap[data.path]);createChildren(data.children || [], root, dm);createFiles(data.files || [], root, dm);});socket.emit('explore');}function createChildren(children, parent, dm) {children.forEach(function(child) {var n = createData(child, parent);dm.add(n);createChildren(child.children || [], n, dm);createFiles(child.files || [], n, dm);});}function createFiles(files, parent, dm){files.forEach(function(file){var n = createData(file, parent);dm.add(n);});}function createData(data, parent){var n = new ht.Data();n.setName(data.name);n.setParent(parent);n.a('path', data.path);idMap[data.path] = n.getId();return n;}</script>
</head>
<body onload="init();">
</body>
</html>

这就是全部的HTML代码,加上空行总共也就50几行,怎么样,有没有感觉HT for Web很强大。废话不多说,来看看这些代码都干了些什么:

  • 要用到socket.io就需要在页面引入<script src=“/socket.io/socket.io.js”></script>,其实在我的项目中并不存在/socket.io/socket.io.js文件,但是却能正常使用,具体什么原因,我就不多说,大家自己研究去吧;

  • 最重要的是要引入HT for Web的核心包<script src=“/lib/core/ht.js”></script>,这个包不引入的话,下面的HT for Web组件就无法使用;

  • 接下来就是代码了,首先创建一个数据容器DataModel,用来存放文件目录的节点数据,再创建一个TreeView对象并引用刚创建到数据容器,接下来通过socket监听file事件,获取服务器返回的数据,在回调函数中通过调用createChildren和createFiles函数,创建文件目录节点对象,并添加到数据容器中,最后是向服务器发起数据请求,即通过socket派发explore事件。

整体的思路是这样子的,当然这离我们要实现的树组件的延迟加载技术还有些差距,那么,HT for Web的HTML5树组件的延迟加载技术是怎么实现的呢?不要着急,马上开始探讨。
首先我们需要改造下获取文件目录的方法walk,因为前面介绍的方法中,使用的是加载整站文件目录,所以我们要将walk方法改造成只获取一级目录结构,改造起来很简单,就是将递归部分改造成获取当前节点就可以了,具体代码如下:

obj.children.push(walk(pa + '/' + item));
// 将上面对代码改成下面的代码
obj.children.push({name: item, path: pa + '/' + item});

这样子服务器就只请求当前请求路径下的第一级文件目录结构。接下来就是要调整下客户端代码了,首先需要给tree设置上loader:

tree.setLoader({load: function(data) {socket.emit('explore', data.a('path'));data.a('loaded', true);},isLoaded: function(data) {return data.a('loaded');}
});

loader包含了两个方法,load和isLoaded,这两个方法的功能分别是加载数据和判断数据是否已经加载,在load方法中,对socket派发explore事件,当前节点的path为参数,向服务器请求数据,之后将当前节点的loaded属性设置为true;在isLoaded方法中,返回当前节点的loaded属性,如果返回为true,那么tree将不会在执行load方法向服务器请求数据。
接下来需要移除createChildren的两个回调方法,并且在createFiles方法中为创建出来的节点的loaded属性设置成true,这样在不是目录的节点前就不会有展开的图标。createChildren和createFiles两个方法修改后的代码如下:

function createChildren(children, parent, dm) {children.forEach(function(child) {var n = createData(child, parent);dm.add(n);});
}function createFiles(files, parent, dm){files.forEach(function(file){var n = createData(file, parent);n.a('loaded', true);dm.add(n);});
}

如此,HT for Web的HTML5树组件延迟加载技术就设计完成了,我在服务器的控制台打印出请求路径,看看这个延迟加载是不是真的,如下图:


看吧,控制台打印的是4条记录,第一条是请求跟目录时打印的,我在浏览器中展开里三个目录,在控制台打印了其对应的目录路径。
等等,现在这个目录看起来好烦,只有文字,除了位子前的展开图标可以用来区别文件和目录外,没有其他什么区别,所以我决定对其进行一番改造,让每一级目录都有图标,而且不同文件对应不同的图标,来看看效果吧:

怎么样,是不是一眼就能看出是什么文件,这个都是样式上面的问题,我就不再一一阐述了,直接上代码:

<!DOCTYPE html>
<html>
<head lang="en"><meta charset="UTF-8"><title></title><script src="/socket.io/socket.io.js"></script><script src="/build/ht-debug.js"></script><script>var socket = io(), idMap = {};function init() {var icons = ['css', 'dir-open', 'dir', 'file', 'flash', 'gif', 'html', 'jar','java', 'mp3', 'pdf', 'png', 'script', 'txt', 'video', 'xml', 'zip'];icons.forEach(function(c){ht.Default.setImage(c, 16, 16, '/test/wyl/images/' + c + '.png');});var dm = window.dm = new ht.DataModel(),tree = new ht.widget.TreeView(dm);tree.setLoader({load: function(data) {socket.emit('explore', data.a('path'));data.a('loaded', true);},isLoaded: function(data) {return data.a('loaded');}});tree.getLabelFont = function(data){return '13px Helvetica, Arial, sans-serif';};tree.getLabelColor = function (data) {return this.isSelected(data) ? 'white' : 'black';};tree.getSelectBackground = function (data) {return '#408EDB';};tree.getIcon = function (data) {var icon = data.getIcon() || 'file';if (data.a('isdir')) {if (this.isExpanded(data)) {icon = 'dir-open';} else {icon = 'dir';}}return icon;};tree.addToDOM();socket.on('file', function(data) {var root = dm.getDataById(idMap[data.path]);createChildren(data.children || [], root, dm);createFiles(data.files || [], root, dm);});socket.emit('explore');}function createChildren(children, parent, dm) {children.forEach(function(child) {var n = createData(child, parent);n.a('isdir', true);dm.add(n);});}function createFiles(files, parent, dm){files.forEach(function(file){var n = createData(file, parent);n.a('loaded', true);dm.add(n);});}function createData(data, parent){var name = data.name,icon = 'file';if (/.jar$/.test(name)) icon = 'jar';else if (/.css$/.test(name)) icon = 'css';else if (/.gif$/.test(name)) icon = 'gif';else if (/.png$/.test(name)) icon = 'png';else if (/.js$/.test(name)) icon = 'script';else if (/.html$/.test(name)) icon = 'html';else if (/.zip$/.test(name)) icon = 'zip';var n = new ht.Data();n.setName(data.name);n.setParent(parent);n.setIcon(icon);n.a('path', data.path);idMap[data.path] = n.getId();return n;}</script>
</head>
<body onload="init();">
</body>
</html>

在最后,附上完整的服务器代码:

var fs = require('fs'),express = require('express'),app = express(),server = require('http').createServer(app),io = require('socket.io')(server),root = '/Users/admin/Projects/ht-for-web/guide';io.on('connection', function(socket){socket.on('explore', function(url){socket.emit('file', walk(url || root));});
});app.use(express.static('/Users/admin/Projects/ht-for-web'));server.listen(5000, function(){console.log('server is listening at port 5000');
});function walk(pa) {var dirList = fs.readdirSync(pa),key = pa.substring(pa.lastIndexOf('/') + 1),obj = {name: key,path: pa,children: [],files: []};dirList.forEach(function(item) {var stats = fs.statSync(pa + '/' + item);if (stats.isDirectory()) {obj.children.push({name: item, path: pa + '/' + item});}else {obj.files.push({name: item, dir: pa + '/' + item});}});return obj;
}

HT for Web的HTML5树组件延迟加载技术实现相关推荐

  1. HT for Web基于HTML5的图像操作(三)

    上篇采用了HTML5的Canvas的globalCompositeOperation属性达到了染色效果,其实CSS也提供了一些常规图像变化的设置参数,关于CSS的过滤器Filter设置可参考 http ...

  2. HT For Web 拓扑图背景设置

    HT For Web 的HTML5拓扑图组件graphView背景设置有多种途径可选择: divBackground:通过css设置graphView对应的div背景 Painter:通过graphV ...

  3. 基于HT for Web的3D拓扑树的实现

    在HT for Web中2D和3D应用都支持树状结构数据的展示,展现效果各异,2D上的树状结构在展现层级关系明显,但是如果数据量大的话,看起来就没那么直观,找到指定的节点比较困难,而3D上的树状结构在 ...

  4. ECharts+BaiduMap+HT for Web网络拓扑图应用

    前一篇谈及到了ECharts整合HT for Web的网络拓扑图应用,后来在ECharts的Demo中看到了有关空气质量的相关报表应用,就想将百度地图.ECharts和HT for Web三者结合起来 ...

  5. HT for Web 3D游戏设计设计--汉诺塔(Towers of Hanoi)

    在这里我们将构造一个基于HT for Web的HTML5+JavaScript来实现汉诺塔游戏. 汉诺塔的游戏规则及递归算法分析请参考http://en.wikipedia.org/wiki/Towe ...

  6. 用HT for Web实现3D列车行进动画

    HT for Web有一套强大的基于WebGL技术的图形引擎,可以用js代码实现3D图像的建模和动画.现在用HT for Web来实现一个3D列车行进的动画来带大家了解一下如何使用这套框架. < ...

  7. 自绘制HT For Web ComboBox下拉框组件

    传统的HTML5的下拉框select只能实现简单的文字下拉列表,而HT for Web通用组件中ComboBox不仅能够实现传统HTML5下拉框效果,而且可以在文本框和下拉列表中添加自定义的小图标,让 ...

  8. 下拉框的value值怎么设置为变量_自绘制HT For Web ComboBox下拉框组件

    传统的HTML5的下拉框select只能实现简单的文字下拉列表,而HT for Web通用组件中ComboBox不仅能够实现传统HTML5下拉框效果,而且可以在文本框和下拉列表中添加自定义的小图标,让 ...

  9. html5 图形组件,数百个 HTML5 例子学习 HT 图形组件 – WebGL 3D 篇

    <数百个 HTML5 例子学习 HT 图形组件 – 拓扑图篇>一文让读者了解了 HT的 2D 拓扑图组件使用,本文将对 HT 的 3D 功能做个综合性的介绍,以便初学者可快速上手使用 HT ...

最新文章

  1. java file_Java IO: File
  2. node.js中模块_在Node.js中需要模块:您需要知道的一切
  3. iOS开发网络——数据缓存
  4. 需求分析说明书(四)
  5. 为UC做准备:部署Exchange 2010及SP1
  6. linux系统下PHP无法调用oracle数据库的解决方法
  7. condition实现通知部分线程
  8. C++常用数据类型和Windows常见数据类型
  9. COM 组件编程--VC知识库读杨老师文章笔记
  10. 二叉树的遍历以及遍历算法的应用(链式存储结构)
  11. 15个网页数据采集中最常遇到的问题(干货)
  12. latex去心领域符号
  13. 基于Sen2Cor软件的Sentinel-2大气校正
  14. 运兴ETF期权投教之50ETF期权新手雷区
  15. instagram封号的原因解析
  16. 在Linux上使用7z的最高压缩比来压缩文件
  17. java的博_小博老师解析Java核心技术 ——I/O流
  18. F2FS源码分析-1.2 [F2FS 元数据布局部分] Superblock结构
  19. quartz的JobDetail属性(durable / concurrent)
  20. 零基础学UI设计要学多久?

热门文章

  1. centos 中设置网卡等相关参数
  2. linux修改文件权限和用户组管理小结
  3. 算法导论读书笔记(7)
  4. 只能输入正整数 已经常用的正则表达式
  5. 查找某节点的所有祖先☆
  6. 诗与远方:无题(六十六)- 清明时节雨纷下
  7. Android事件处理之处理键盘事件
  8. Hadoop开启Kerberos安全模式
  9. java.nio.DirectByteBuffer管理堆外内存
  10. java StringUtils方法全览