在实际的项目中,左边树形菜单,提供各种功能点击,右边一个面板,随着左边节点的选择表现不同的功能内容,这是一个相当经典的布局,在Ext框架中,有两个控件TreePanel和TabPanel刚好完成这些功能,本文就这两个控件的搭配使用和点击左边树节点引起右边内容变化的方法作一个简单的介绍。首先看下面的具体的代码。
Js代码
1.<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2.<html xmlns="http://www.w3.org/1999/xhtml">
3.<head>
4.<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5.<title>TabPanel和Tree控件搭配测试</title>
6.<link rel="stylesheet" type="text/css" media="all" href="../ext/resources/css/ext-all.css" />
7.<script type="text/javascript" src="../ext/adapter/ext/ext-base.js"></script>
8.<script type="text/javascript" src="../ext/ext-all.js"></script>
9.<script type="text/javascript" src="../ext/build/locale/ext-lang-zh_CN.js"></script>
10.<script type="text/javascript">Ext.BLANK_IMAGE_URL = '../ext/resources/images/default/s.gif';</script>
11.<script type="text/javascript">
12.//左边功能树
13.var menuTree = new Ext.tree.TreePanel({
14. region:'west',
15. title:'功能菜单',
16. width:180,
17. minSize:150,
18. maxSize:200,
19. split:true,
20. autoScroll:true,
21. autoHeight:false,
22. collapsible:true,
23. rootVisable:false, //不显示根节点
24. root:new Ext.tree.TreeNode({
25. id:'root',
26. text:'功能菜单',
27. draggable:false,
28. expanded:true
29. })
30.});
31.
32.//添加第一个节点(html)
33.menuTree.root.appendChild(new Ext.tree.TreeNode({
34. id:'htmlPanel',
35. text:'通过html打开',
36. listeners:{
37. 'click':function(node, event) {
38. event.stopEvent();
39. var n = contentPanel.getComponent(node.id);
40. if (!n) { //判断是否已经打开该面板
41. n = contentPanel.add({
42. 'id':node.id,
43. 'title':node.text,
44. closable:true, //通过html载入目标页
45. html:'<iframe scrolling="auto" frameborder="0" width="100%" height="100%" src="iframe.html"></iframe>'
46. });
47. }
48. contentPanel.setActiveTab(n);
49. }
50. }
51.}));
52.
53.//添加第二个节点(autoLoad)
54.menuTree.root.appendChild(new Ext.tree.TreeNode({
55. id:'autoLoadPanel',
56. text:'通过autoLoad打开',
57. listeners:{
58. 'click':function(node, event) {
59. event.stopEvent();
60. var n = contentPanel.getComponent(node.id);
61. if (!n) { ////判断是否已经打开该面板
62. n = contentPanel.add({
63. 'id':node.id,
64. 'title':node.text,
65. closable:true,
66. autoLoad:{url:'auto.php', scripts:true} //通过autoLoad属性载入目标页,如果要用到脚本,必须加上scripts属性
67. });
68. }
69. contentPanel.setActiveTab(n);
70. }
71. }
72.}));
73.
74.//添加第三个节点(function)
75.menuTree.root.appendChild(new Ext.tree.TreeNode({
76. id:'functionPanel',
77. text:'通过函数打开',
78. listeners:{
79. 'click':function(node, event) {
80. event.stopEvent();
81. var n = contentPanel.getComponent(node.id);
82. if (!n) {
83. var p = new fnPanel();
84. p.id = node.id;
85. p.title = node.text;
86. n = contentPanel.add(p);
87. }
88. contentPanel.setActiveTab(n);
89. }
90. }
91.}));
92.
93.//通过扩展来构建要创建的面板
94.fnPanel = Ext.extend(Ext.Panel, {
95. closable:true,
96. autoScroll:true,
97. layout:'fit', //如果用函数来创建该面板的话,布局必须设置为fit,否则不会显示该面板中的内容
98.
99. //创建面板内容
100. createFormPanel:function() {
101. return new Ext.form.FormPanel({
102. buttonAlign:'center',
103. labelAlign:'right',
104. frame:false,
105. bodyBorder:false,
106. bodyStyle:'padding:25px',
107. items:[{
108. xtype:'textfield',
109. fieldLabel:'用户名',
110. width:350,
111. name:'username'
112. },{
113. xtype:'textfield',
114. fieldLabel:'密 码',
115. width:350,
116. name:'password'
117. }],
118. buttons:[{text:'登陆'}, {text:'取消'}]
119. });
120. },
121.
122. //重装控件初始化函数,在该函数中完成面板中内容的初始化
123. initComponent:function() {
124. fnPanel.superclass.initComponent.call(this);
125. this.fp = this.createFormPanel();
126. this.add(this.fp);
127. }
128.});
129.
130.//右边具体功能面板区
131.var contentPanel = new Ext.TabPanel({
132. region:'center',
133. enableTabScroll:true,
134. activeTab:0,
135. items:[{
136. id:'homePage',
137. title:'首页',
138. autoScroll:true,
139. html:'<div style="position:absolute;color:#ff0000;top:40%;left:40%;">Tree控件和TabPanel控件结合功能演示</div>'
140. }]
141.});
142.
143.Ext.onReady(function(){
144. new Ext.Viewport({
145. layout:'border', //使用border布局
146. defaults:{activeItem:0},
147. items:[menuTree, contentPanel]
148. });
149.});
150.</script>
151.</head>
152.<body>
153.</body>
154.</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>TabPanel和Tree控件搭配测试</title>
<link rel="stylesheet" type="text/css" media="all" href="../ext/resources/css/ext-all.css" />
<script type="text/javascript" src="../ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../ext/ext-all.js"></script>
<script type="text/javascript" src="../ext/build/locale/ext-lang-zh_CN.js"></script>
<script type="text/javascript">Ext.BLANK_IMAGE_URL = '../ext/resources/images/default/s.gif';</script>
<script type="text/javascript">
//左边功能树
var menuTree = new Ext.tree.TreePanel({
region:'west',
title:'功能菜单',
width:180,
minSize:150,
maxSize:200,
split:true,
autoScroll:true,
autoHeight:false,
collapsible:true,
rootVisable:false, //不显示根节点
root:new Ext.tree.TreeNode({
id:'root',
text:'功能菜单',
draggable:false,
expanded:true
})
});
//添加第一个节点(html)
menuTree.root.appendChild(new Ext.tree.TreeNode({
id:'htmlPanel',
text:'通过html打开',
listeners:{
'click':function(node, event) {
event.stopEvent();
var n = contentPanel.getComponent(node.id);
if (!n) { //判断是否已经打开该面板
n = contentPanel.add({
'id':node.id,
'title':node.text,
closable:true, //通过html载入目标页
html:'<iframe scrolling="auto" frameborder="0" width="100%" height="100%" src="iframe.html"></iframe>'
});
}
contentPanel.setActiveTab(n);
}
}
}));
//添加第二个节点(autoLoad)
menuTree.root.appendChild(new Ext.tree.TreeNode({
id:'autoLoadPanel',
text:'通过autoLoad打开',
listeners:{
'click':function(node, event) {
event.stopEvent();
var n = contentPanel.getComponent(node.id);
if (!n) { ////判断是否已经打开该面板
n = contentPanel.add({
'id':node.id,
'title':node.text,
closable:true,
autoLoad:{url:'auto.php', scripts:true} //通过autoLoad属性载入目标页,如果要用到脚本,必须加上scripts属性
});
}
contentPanel.setActiveTab(n);
}
}
}));
//添加第三个节点(function)
menuTree.root.appendChild(new Ext.tree.TreeNode({
id:'functionPanel',
text:'通过函数打开',
listeners:{
'click':function(node, event) {
event.stopEvent();
var n = contentPanel.getComponent(node.id);
if (!n) {
var p = new fnPanel();
p.id = node.id;
p.title = node.text;
n = contentPanel.add(p);
}
contentPanel.setActiveTab(n);
}
}
}));
//通过扩展来构建要创建的面板
fnPanel = Ext.extend(Ext.Panel, {
closable:true,
autoScroll:true,
layout:'fit', //如果用函数来创建该面板的话,布局必须设置为fit,否则不会显示该面板中的内容
//创建面板内容
createFormPanel:function() {
return new Ext.form.FormPanel({
buttonAlign:'center',
labelAlign:'right',
frame:false,
bodyBorder:false,
bodyStyle:'padding:25px',
items:[{
xtype:'textfield',
fieldLabel:'用户名',
width:350,
name:'username'
},{
xtype:'textfield',
fieldLabel:'密 码',
width:350,
name:'password'
}],
buttons:[{text:'登陆'}, {text:'取消'}]
});
},
//重装控件初始化函数,在该函数中完成面板中内容的初始化
initComponent:function() {
fnPanel.superclass.initComponent.call(this);
this.fp = this.createFormPanel();
this.add(this.fp);
}
});
//右边具体功能面板区
var contentPanel = new Ext.TabPanel({
region:'center',
enableTabScroll:true,
activeTab:0,
items:[{
id:'homePage',
title:'首页',
autoScroll:true,
html:'<div style="position:absolute;color:#ff0000;top:40%;left:40%;">Tree控件和TabPanel控件结合功能演示</div>'
}]
});
Ext.onReady(function(){
new Ext.Viewport({
layout:'border', //使用border布局
defaults:{activeItem:0},
items:[menuTree, contentPanel]
});
});
</script>
</head>
<body>
</body>
</html>
上面代码中,构建了两个控件menuTree和contentPanel,menuTree用来显示具体功能菜单,contentPanel用来展示具体功能内容,menutTree中的节点是通过appendChild()方法手动加上去的,而且为了介绍方便,每个节点都添加了一个处理点击事件的函数,在具体应用中,还可以使用AsyncTreeNode()和TreeLoader()动态载入节点,下面着重介绍点击树节点引起功能区变化的方法,上面代码中用到了三种方法。
(1)通过TabPanel控件的html属性配合<iframe>实现。该方法是利用html属性中包含<iframe>的语法来调用另一个页面,具体见代码。该方法实现比较简单,只要重新编辑一个html文件即可以了,而且如果要在新生成的页面中再使用Ext的控件也比较简单,也比较好控制,只要像一个页面情况下使用就可以了,因为他本身就是一个完整的html文件。而该方法的缺点就是资源占用厉害,是三种方法中占有最厉害的,而且还有Ext的重复加载的问题(不知道Ext库中考虑这种情况了没有),另外就是新的页面载入速度也是最慢的。
(2)通过TabPanel控件的autoLoad属性实现。该方法是利用autoLoad属性,它有很多参数,其中有两个比较重要,url表示要载入的文件,scripts表示载入的文件是否含有脚本,该属性相当重要,如果在新的页面中要创建Ext控件,必须指定该参数。该方法实现较前一个复杂,因为引入的文件不是一个完整的html文件,有可能只是内容的一部分,但是资源占用较少,而且载入速度较快(它有一个载入指示),但缺点就是如果是载入的是一个单纯html文件(*.html),在字符编码上处理很麻烦,经常出现乱码,我提供的源码中是一个PHP文件,用PHP文件也只是一个作用,改变输出的字符编码,用html能够实现同样的功能,但会是乱码,我不知道怎样解决这个问题。
(3)通过自己构建新的面板来实现。该方法是通过继承Panel面板,然后在该面板中加入要显示的内容,再重载initComponet()方法,最后把该面板添加到TabPanel中,该方法中一个要注意的地方,新生成的页面布局一定要用fit,否则该面板中的内容不能显示出来。该方法是所有方法中最复杂的,而且由于采用了fit布局,新生成的页面中的元素不好控制,我例子中的表单就生成的比较乱。但载入速度是最快的,可能是少了载入指示吧,资源占用跟第二种方法差不多。
上面三种方法中,我比较喜欢第二种实现方面,简单好控制,而且还有一个载入指示。不知道大家有没有其他的方法。一起讨论讨论。