起初该工具运行的很好,但随着文档数目的增加,文件夹的层级加深,一些问题就显现了,原先的设计是采用 FileSystemObject 将文档目录进行了一个递归遍历,把遍历结果组织成 Json 文件返回给浏览器,在文档数目不大,文件夹层级不深的情况下,是可以工作的很好的,反正是在公司内网使用 :),现在文档数目增加了,就不得不考虑优化的工作了,于是决定改写一下,让 TreePanel 支持异步的数据请求。
在网上查了很多资料,不少的范例都是介绍使用 asyncTreeNode、TreeLoader 来实现异步数据请求,最后还是上官网论坛看到一帖子,明确的指出 TreePanel 已经不再使用 TreeNodes 来实现异步数据请求了,具体什么版本开始不知道,帖子的发布时间是2011年3月份的,所以我认为在 ExtJS 4 这个版本上肯定是不支持了,以下是原文地址:
点击打开链接
在上述的链接中,还留意到其实在4.x版本下的 store 已经是按异步模式进行优化的,除非你在返回的数据中定义了 children ,否则当 TreePanel 和 store 配合使用时,在展开树节点时 store 是会自动引发请求来更新展开节点的数据的,几乎不用写什么代码就可以实现开篇时所提出的需求。原文如下:
于是去找开发包自带的范例,找到 examples\tree\ 下的 reorder.html,reorder.js,reorder.js的代码如下:
Ext.require([ 'Ext.tree.*', 'Ext.data.*', 'Ext.tip.*' ]); Ext.onReady(function() { Ext.QuickTips.init(); var store = Ext.create('Ext.data.TreeStore', { proxy: { type: 'ajax', url: 'get-nodes.php' }, root: { text: 'Ext JS', id: 'docs', expanded: true }, folderSort: true, sorters: [{ property: 'text', direction: 'ASC' }] }); var tree = Ext.create('Ext.tree.Panel', { store: store, renderTo: 'tree-div', height: 300, width: 250, title: 'Files', useArrows: true }); });
我跟踪了这个代码的执行,当首次打开 reorder.html 这个页面时,会引发一次对 get-nodes.php 的请求,此时的请求链接 大致上是这样的:
..../get-nodes.php?_dc=8761836491987632467&node=docs&............
这里着重要说明的是node参数,这个参数就是在定义 store 对象时指定的 id 值,请留意上面的代码,在 root : {} 的定义里,这个参数的实际意义是告诉 get-nodes.php 以 docs 这个位置开始做为根节点开始构建 TreePanel 所需要的树,仅需返回当前层的数据,以文件系统的目录结构为例,假如 docs下的目录结构如下:
收到请求后,get-nodes.php 接收到 node参数指向 docs,于是返回docs下的文件夹和文件,但不会继续往下进行递归遍历,因此返回的数据有两种节点,一种是叶子节点,代表文件,一种是非叶子节点,代表文件夹,请留意文件夹节点并没有 children 项。Json数据大概是以下这个样子:
{text: '.',children:[ {id:'docs/dealers',text:'dealers',expanded:false}, // 文件夹节点 {id:'docs/Test2',text:'Test2',expanded:false}, {id:'docs/知识库',text:'知识库',expanded:false}, {text:'ShowIIS.asp',leaf:true}, {text:'startPage.png',leaf:true} ]}
值得留意的是,文件夹节点的 id 值的设置,这是一种约定,在每个文件夹节点中用 id 来定义该文件夹的寻址路径,这样当用户在 TreePanel 单节这个文件夹节点时,stroe 对象将会以这个 id 值做为参数再次向服务端发起请求,例如:用户单击节点 “知识库” ,引发的请求的链接会是以下这个样子:
..../get-nodes.php?_dc=9384750928743059&node=docs/知识库&............因为在上一次请求返回 “知识库” 这个节点信息时 get-nodes.php 的处理代码定义了其 id 值为 docs/知识库,所以单击 知识库 这个节点 store 会以该节点的 id 值做为参数引发新的请求,这正是 store 实现分次请求的核心机制。
当请求的数据回来后 TreePanel 会自动将数据添加到被点击的节点之下,以此类推,返回 知识库下 编程技术 文件夹节点的 id 值就是:docs/知识库/编程技术,基于这个机制,TreePanel也就实现了按展开的节点来分次请求数据。
想看完整的例子,可以找开发包自带的,位置在:examples\tree\ 下的 reorder.html,reader.js,get-nodes.php
定义特权方法
在构造函数内部通过this关键字定义的的方法,可以被实例化的对象继承所调用。
var _name = name; //私有属性
//特权方法
this.getName = function() {
return _name;
};
this.setName = function(name) {
_name = name;
};
};
var s1 = new Student('zhangsan');
s1.getName(); //zhangsan
特权方法的作用
特权方法能够在构造函数外面公开访问(仅限于实例化的对象),而且还能够访问私有成员和方法,因此用来做为对象或者构造函数的接口最合适不过了,通过特权方法我们可以控制公有方法对私有属性或方法的访问。 在JS框架的扩展中有很多应用。
特权方法与公有方法的区别
相同点:1. 都可以在构造函数外部公开访问。2. 都可以访问公有属性
不同点:有2点
1. 每个实例都要拥有一份特权方法的副本(除在单例中使用外,需要考虑内存),而公有方法为所有实例共享
var s1 = new Student('zhangsan');
var s2 = new Student('lisi');
//两实例的特权方法的引用不相同, 说明在对象实例化的时特权方法被重新创建
console.log(s1.getName === s2.getName); //false
2. 特权方法可以访问私有属性和方法,而公有方法不能。
//公有方法不能访问私有属性
Student.prototype.myMethod = function() {
console.log(_name); //ReferenceError: _name is not defined
};
s1.myMethod();
小结:特权方法作为构造函数的接口,公有方法可以通过特权方法访问私有属性和方法
本文链接
Dom:英文全称-Document Object Model 译成中文即是:文档对像模型.听起来很术语,其实就是文档内容的结构关系.文档类型可以是HTML或XML
Dom具有对Html文件和XML文件元素的访问控制能力,简单点说利用Dom可以对某个html或xml文件添加,修改,删除元素.更改其现有的结构或内容.如果你未接触过Dom,你会发现Dom太神奇了...不管你是菜鸟还是高手,在这个注重用户体验的web设计时代里,Dom是至关重要的. 如果你是一名有经验的web设计者,你应该看到过或用过以下这些命令或方法 getElementById getElementsByTagName offsetParent appendChild getAttribute 不过至今仍有人认为这些都是JavaScript中的东西,其实不然,这些全是Dom中很重要的方法!
Dom手册下载地址
Dom并非一种编程语言,Dom只是提供了一系列的接口,利用Dom的这些接口可以很方便的读取,修改,删除Html和XML文件中的标签元素和文本内容.在这里我们侧重于讲解Dom对Html文件的操作.
那么Dom是如何读取和管理Html文件的呢?首先你必须要了解html的源码结构.看图
如果你有学过或写过Html,那么你会对上图一目了然.我想要说明的就是Html的源码结构是有层次的,而且标签与杯签之间还存在着父子,或相邻的关系.上图不难看出HTML这个标签是最顶级的.最上层的.也可以理解成html文件的根.其次是Head与Body标签.这两个标签是相邻的.也可以理解成兄弟关系.但他们都属于html的子标签或称为子元素.然后Body标签内包含了Table,Div,Div.这三个标签你可以理解为Body的子标签或子元素.Body为父他们为子.Head所含的标签也是同理.另外第一个div内包含了另一个div.第二个div内包含了一些文本内容.他们的关系也是父子关系.Dom正是利用了Html源码的这种关系结构.而巧妙的在你的html源码中行走自如.犹如一位武林高手一般.尽情地施展他的"凌波微步".看下面的代码.代码结构与上图是吻合的.不同的是多了几个按扭来执行一些dom的指令操作.运行以后你便走进了Dom的神秘与精彩世界!!!
<html>
<head>
<title>这是网页的标题</title>
<link />
<meta />
<body>
<table border="1"><table>
<div><div></div></div>
<div>文本内容</div>
<input type="button" value="弹出html标签" onclick="alert_HTML()"/>
<input type="button" value="弹出body标签" onclick="alert_Body()"/>
<input type="button" value="弹出head标签" onclick="alert_Head()"/>
<input type="button" value="修改网页标题" onclick="up_Title()"/>
<input type="button" value="更改表格" onclick="up_Table()"/>
<input type="button" value="获取第一个div和他的子元素" onclick="get_Div()"/>
<input type="button" value="更改第二个div中的文本内容" onclick="up_div_text()"/>
</body>
</html>
<script type="text/javascript">
function alert_HTML(){ //弹出html标签函数
var html = document.documentElement;
alert(html.tagName);
}
function alert_Body(){ //弹出body标签函数
var body = document.body;
alert(body.tagName);
}
function alert_Head(){//弹出head标签函数,
var html = document.documentElement;
//head是html标签中的第一个子元素
//childNodes可以获取某一标签内的所有子元素
var head = html.childNodes[0].tagName;
alert(head);
}
function up_Title(){
//注意title标签内的"这是网页的标题"将被改变.
document.title = "Web圈提提供的Dom图解入门教程";
}
function up_Table(){//为表格添加行,添加列并写入文本内容
var Table = document.getElementsByTagName("table")[0];//获取网页内第一个表格
var Tr = Table.insertRow(0);//为表格添加一行
var Td = Tr.insertCell(0);//为新建的行,添加一列
Td.innerHTML = "我是表格中的文本"; //利用innerHTML属性向td写入文本
}
function get_Div(){//获取第一个div和他的孩子
var div = document.getElementsByTagName("div")[0];
alert("我是第一个"+div.tagName);
var child_div = div.childNodes[0];//虽然是子div,但是按解析顺序他在该页内是第二个出现的div,
alert("我是第一个div的子元素.我也是"+child_div.tagName);
}
function up_div_text(){
var div = document.getElementsByTagName("div")[2];//其实如果按解析顺序该div在本页应该是第3个,
div.innerHTML = "欢迎阅读web圈提供的Dom图解入门教程.www.jb