本章涵蓋了高級組件,好比 tree 和 data view。它將爲讀者呈現一個示例項目爲 圖片瀏覽器,它使用 tree 和 data view 組件。如下是本章將要討論的主題:css
轉載請註明出處:http://www.jeeboot.com/archives/1227.htmlhtml
本章的主要目標是探索 tree panel 和 data view 而且使用他們來構建一個示例項目圖片瀏覽器。圖片瀏覽器的最終展現效果以下圖。node
這個項目中的最重要的組件是 tree panel 和 data view 。本項目中使用的組件和概念有:git
除了 tree panel 和 data view 你已經在以前的章節中學習了全部的咱們目前已用到的知識。因此在本章中,咱們首先學習 tree panel 和 data view。github
這在 ExtJS 中是一個很是強大且經常使用的組件,你能夠使用它構建任意類型的樹。一個 tree panel 是一個樹形結構的具備層次化數據的UI。json
它和 Ext.grid.Panel 類似, Ext.tree.Panel 也繼承自Ext.panel.Table 。因此,它也是支持多列的。bootstrap
和 grid panel 不一樣的是,tree panel 須要一個 tree store (Ext.Store.TreeStore)。 tree store 具備一些 tree panel 的功能所需使用的特殊的屬性。瀏覽器
咱們來用一個簡單的例子演示。tree panel 至少須要一個 tree store 來提供數據。咱們首先來建立 tree store 並硬編碼內置數據:app
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
var store = Ext.create('Ext.data.TreeStore', {
root: {
expanded: true,
text: 'Continents',
children: [{
text: 'Antarctica',
leaf: true
}, {
text: 'South America',
expanded: true,
children: [{
text: 'Brazil',
leaf: true
}, {
text: 'Chile',
leaf: true
}]
}, {
text: 'Asia',
expanded: true,
children: [{
text: 'India',
leaf: true
},{
text: 'China',
leaf: true
}]
}, {
text: 'Africa',
leaf: true
}]
}
});
|
接着繼續建立 Ext.tree.Panel :dom
1
2
3
4
5
6
7
8
|
Ext.create('Ext.tree.Panel', {
title: 'Basic Tree',
width: 200,
height: 450,
store: store,
rootVisible: true,
renderTo: Ext.getBody()
});
|
下列截圖爲以上代碼的輸出結果:
如今,咱們建立一個高級點的樹,它是能夠拖拽的。同時還須要用到 tree panel 和 tree store 的一些額外選項。拖拽只須要添加一個插件叫作 treeviewdragdrop 。如如下代碼所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
var store = Ext.create('Ext.data.TreeStore', {
root: {
expanded: true,
text: 'Continents',
checked: false,
children: [{
text: 'Antarctica',
leaf: true ,
checked: false
},{
text: 'South America',
expanded: false,
checked: true,
children: [{
text: 'Chile',
leaf: true,
checked: true
}]
},{
text: 'Asia',
expanded: true,
checked: true,
children: [{
text: 'India',
leaf: true,
checked: true
},{
text: 'China',
leaf: true,
checked: true
}]
},{
text: 'Africa',
leaf: true,
checked: true
}]
}
});
Ext.create('Ext.tree.Panel', {
title: 'Basic Tree',
width: 200,
height: 450,
store: store,
rootVisible: true,
useArrows: true,
lines: false,
renderTo: Ext.getBody(),
viewConfig: {
plugins: {
ptype: 'treeviewdragdrop',
containerScroll: true
}
}
});
|
如如下截圖所示的輸出。我把節點 South America 拖拽至 Asia 節點之下:
你能夠將多個列添加到 tree ,同時也能建立 tree grid 。默認 tree 包含一列,用的是 tree store 中節點的文本字段。
在這個 store 中,你能夠看到在每一個節點上除了節點名稱,還添加了一些其餘的字段,這些字段用於在 tree panel 的列展現上。tree grid 的功能有例如 列調整,排序,過濾等等,如下是代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
var store = Ext.create('Ext.data.TreeStore', {
root: {
expanded: true,
text: 'Continents',
children: [{
name: 'Antarctica',
population: 0,
area: 14,
leaf: true
},{
name: 'South America',
population: 385 ,
area: 17.84,
expanded: false,
children: [{
name: 'Chile',
population: 18,
area: 0.7,
leaf: true,
}]
},{
name: 'Asia',
expanded: true,
population: 4164,
area: 44.57,
children: [{
name: 'India',
leaf: true,
population: 1210,
area: 3.2
},{
name: 'China',
leaf: true,
population: 1357,
area: 9.5
}]
},{
name: 'Africa',
leaf: true,
population: 1110,
area: 30
}]
}
});
|
如下的 grid 和上面的 tree panel 差很少同樣,只是添加爲多列了,這個 xtyp treecolumn 提供縮進和文件夾結構。像一個正常的 grid 同樣,tree grid 的列能夠是任意類型的例如 checkbox,picture,button,URL 等等。
默認列大小是可調整的,若是須要你也能夠固定它的寬度。看下面的代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
Ext.create('Ext.tree.Panel', {
title: 'Tree Grid',
width: 500,
height: 450,
store: store,
rootVisible: false,
useArrows: true,
lines: false,
scope: this,
renderTo: Ext.getBody(),
columns: [{
xtype: 'treecolumn',
text: 'Name',
flex: 1,
sortable: true,
dataIndex: 'name'
} , {
text: 'Population (millons)',
sortable: true,
width: 150,
dataIndex: 'population'
} , {
text: 'Area (millons km^2)',
width: 150,
sortable: true,
dataIndex: 'area'
}]
});
|
這是上面 Tree Grid 的輸出結果:
Ext.view.View (xtype:dataview) 一個現實數據的自定義模板。你須要提供自定義的模板和數據源(store)。模板應該使用 Ext.XTemplate 。
data view 提供了內置的事件,例如 click,double-click,mouseover,mouseout,等等。
首先咱們建立一個簡單的 model 名爲 Person ,還須要建立一個 store 並持有 Person 的列表,如如下代碼所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
Ext.define('Person', {
extend : 'Ext.data.Model',
fields : [ {
name : 'name',
type : 'string'
}, {
name : 'age',
type : 'int'
}, {
name : 'gender',
type : 'int'
} ]
});
Ext.create('Ext.data.Store', {
id : 'employees',
model : 'Person',
data : [{
name : 'Mike',
age : 22,
gender : 0
},{
name : 'Woo',
age : 32,
gender : 1
},{
name : 'John',
age : 33,
gender : 1
},{
name : 'Kalai',
age : 25,
gender : 0
}]
});
|
而後咱們要來建立這個模板。下列模板使用 HTML 的 table 元素來呈現自定義格式的數據。
在模板中使用一個 model 的字段時,你能夠使用花括號包括字段名的方式來使用它,例如:{fieldname}
XTemplate 支持有條件的展示和 if 語句,如如下代碼所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
var empTpl = new Ext.XTemplate(
'<tpl for=".">',
'<div style="margin-bottom: 10px;" class="data-view">',
'<table style="width:100%">',
'<tr>',
'<td style="font-size: 100px;width:100px;" rowspan="3"><i class="fa fa-user"></i></td>',
'<td>Name: {name}< /td>',
'</tr>',
'<tr>',
'<td>Age:{age}< /td>',
'</tr>',
'<tr>',
'<td>Gender: <tpl if="gender == 1">',
'<i class="fa fa-mars"></i>',
'<tpl else>',
'<i class="fa fa-venus"></i>',
'</tpl></td>',
'</tr></table> ',
'</div>',
'</tpl>'
) ;
|
看上面的例子,我使用了 awesome 字體圖標的樣式。你須要添加下列代碼到你的 HTML 文件才行:
1
|
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font- awesome/4.3.0/css/font-awesome.min.css">
|
一下代碼建立了一個 data view,而且它指定了使用的數據源 store ,template 和 itemSelector :
1
2
3
4
5
6
7
8
9
10
11
|
Ext.create('Ext.view.View', {
store : Ext.getStore('employees'),
tpl : empTpl,
itemSelector : 'div.data-view',
renderTo : Ext.getBody(),
listeners : {
itemclick : function(node, rec, item, index, e) {
alert(rec.data.name);
}
}
});
|
itemSelector 是一個必須的簡單 CSS 選擇器。這裏 itemSelector 是應用於在 template 中的 HTML ,就是使用 data-view 類的 div 標籤,最終根據這個模板,你在 data view 中選擇的每個 item ,就是這樣一個 div 標籤,設置了 itemSelector 屬性,data view 會知道如何處理這些節點,itemSelector 是用於將 DOM 節點映射到 records 。
你能夠監聽的事件例如 click ,double-click ,等等,以上代碼已經添加了監聽,下列是輸出結果:
慣例,咱們將用一個示例項目來回顧本章所學,下面是示例項目的最終設計效果:
經過查看這個設計,你會看到咱們使用的最重要的組件就是 tree panel 和 data view 。它們如何使用和一些概念已經在本章的前面部分說起。
咱們看看, 項目的目錄結構。
下列視圖代碼是本項目的重要部分。這個視圖呈現了應用中大部分可視組件。它使用 tree panle 和 data view :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
Ext.define('PE.view.pics.Pics', {
extend : 'Ext.panel.Panel',
/* Marks these are required classes to be to loaded before loading this view */
requires : [ 'PE.view.pics.PicsController' ],
xtype : 'app-pics',
controller : 'pics',
items : [ {
xtype : 'container',
layout : 'hbox',
cls : 'pics-list',
items : [ {
xtype : 'treepanel',
width : 200,
height : '100%',
store : 'albums',
border : true,
useArrows : true,
cls : 'tree',
rootVisible : false,
listeners : {
itemdblclick : 'onNodeSelect'
},
dockedItems : [ {
xtype : 'toolbar',
dock : 'top',
ui : 'footer',
items : [{
xtype : 'component',
flex : 1
},{
xtype : 'button',
text : 'Upload',
cls : 'btn-blue'
}]
}]
},{
xtype : 'dataview',
reference : 'picsList',
cls : 'pics-list-content',
store : 'pics',
tpl : [
'<tpl for=".">',
'<div class="thumb"><img src="{url}" title=""></div>',
'</tpl>'
],
multiSelect : true,
minHeight : 400,
flex : 1,
trackOver : true,
overItemCls : 'x-item-over',
itemSelector : 'div.thumb',
emptyText : 'No images to display'
}]
}]
});
|
控制器 ViewController 裏處理了 tree panel 的 itemdblclick 事件,只顯示所選擇節點下的圖片。
還有一個 upload 按鈕的 click 事件,這裏是未處理的。額,這是你的做業啦。看看下列代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
Ext.define('PE.view.pics.PicsController', {
extend : 'Ext.app.ViewController',
alias : 'controller.pics',
views : [ 'PE.view.pics.Pics' ],
requires : [ 'PE.store.Pics', 'PE.store.Albums' ],
onNodeSelect : function(node, rec, item, index, e){
var albums = [];
albums.push(rec.id);
rec.childNodes.forEach(function(item) {
albums.push(item.id);
});
Ext.getStore('pics').filter({
property : 'albumId',
operator : 'in',
value : albums
});
}
});
|
Model 和 Store 的代碼在這兒。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
Ext.define('Pic', {
extend : 'Ext.data.Model',
fields : [ 'id', 'url', 'albumId' ]
});
Ext.define('PE.store.Pics', {
extend : 'Ext.data.Store',
storeId : 'pics',
model : 'Pic',
proxy : {
type : 'rest',
url : 'pics', // URL that will load data with respect to start and limit params
reader : {
type : 'json'
}
}
});
Ext.create('PE.store.Pics').load();
Ext.define('PE.store.Albums', {
extend : 'Ext.data.TreeStore',
storeId : 'albums',
root : {
expanded : true,
children : [ {
id : 100,
text : ' California',
expanded : true,
children : [ {
id : 600,
text : ' Big Sur',
leaf : true
}, {
id : 500,
text : ' Yosemite',
leaf : true
}]
}, {
id : 400,
text : ' Arizona',
expanded : true,
children : [ {
id : 300,
text : ' Horseshoe bend',
leaf : true
}]
}, {
id : 200,
text : ' Home',
leaf : true
}, {
id : 700,
text : ' India',
expanded : true,
children : [ {
id : 800,
text : ' Ooty',
leaf : true
}, {
id : 900,
text : ' Chennai',
leaf : true
}, {
id : 1000,
text : ' Munnar',
leaf : true
} ]
} ]
}
});
Ext.create('PE.store.Albums');
|
我是用的 Go 語言爲此項目寫的 REST API 。完整可用的代碼在這裏 https://github.com/ananddayalan/extjs-byexample-picture-explorer
圖片瀏覽器這個示例是一個很是簡單並用來學習 tree panel 和 data view 使用是很合適的。也能夠經過添加更多功能來改進這個例子。例如如何經過拖拽將圖片從一個相冊移動到另外一個相冊中。 我會留給你做爲一個編碼的練習,但在這裏,我給你簡要的概述一下拖拽功能,這將幫助你在此項目中添加拖拽功能。
任意元素或組件都能支持拖拽。使用拖拽有三個重要的事情:
想要拖拽一個 item ,你須要爲每個元素建立 Ext.dd.DD 實例。
查看下列代碼,經過建立 Ext.dd.DD 讓全部使用 pics 類的 div 元素成爲可拖拽的:
1
2
3
4
5
6
|
// Configure the pics as draggable var pics = Ext.get('pics').select('div');
Ext.each(pics.elements, function(el) {
var dd = Ext.create('Ext.dd.DD', el, ' picsDDGroup', {
isTarget : false
});
});
|
使用 Ext.dd.DDTarget 建立放置容器。如下代碼爲全部的使用 album 類的 div 元素建立放置目標:
1
2
3
4
5
|
var albums = Ext.get('album').select('div');
Ext.each(albums.elements, function(el) {
var albumDDTarget = Ext.create('Ext.dd.DDTarget', el,
'picsDDGroup');
});
|
當一個可拖拽項放置到一個放置容器,咱們須要從這個 item 的源位置將它移動到目標位置。這經過覆蓋 DD 的onDragDrop 方法來實現。看一看下列代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
var overrides = {
onDragDrop : function(evtObj, targetElId) {
var dropEl = Ext.get(targetElId);
if (this.el.dom.parentNode.id != targetElId) {
dropEl.appendChild(this.el);
this.onDragOut(evtObj, targetElId);
this.el.dom.style.position = '';
this.el.dom.style.top = '';
this.el.dom.style.left = '';
} else {
this.onInvalidDrop();
}
},
onInvalidDrop : function() {
this.invalidDrop = true;
}
};
|
由於 DD 元素已是實例了,重寫的方法須要應用 Ext.apply(dd, overrides) ,如如下代碼所示:
1
2
3
4
5
6
7
8
|
var albums = Ext.get('album').select('div');
var pics = Ext.get('pics').select('div');
Ext.each(pics.elements, function(el) {
var dd = Ext.create('Ext.dd.DD', el, ' picsDDGroup', {
isTarget : false
});
Ext.apply(dd, overrides);
});
|
在本章中,你學習到如何使用拖拽功能。咱們也看了幾個高級組件:tree panel 和 data view。最後結合所學建立了一個示例項目。