惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
The Exploit Database - CXSecurity.com
F
Fortinet All Blogs
U
Unit 42
F
Full Disclosure
雷峰网
雷峰网
博客园 - 司徒正美
云风的 BLOG
云风的 BLOG
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tailwind CSS Blog
The Cloudflare Blog
Last Week in AI
Last Week in AI
罗磊的独立博客
D
DataBreaches.Net
C
Check Point Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
O
OpenAI News
C
CXSECURITY Database RSS Feed - CXSecurity.com
aimingoo的专栏
aimingoo的专栏
S
Security @ Cisco Blogs
大猫的无限游戏
大猫的无限游戏
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
S
SegmentFault 最新的问题
NISL@THU
NISL@THU
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Hacker News
The Hacker News
Webroot Blog
Webroot Blog
Security Latest
Security Latest
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Google DeepMind News
Google DeepMind News
酷 壳 – CoolShell
酷 壳 – CoolShell
N
News | PayPal Newsroom
P
Proofpoint News Feed
B
Blog RSS Feed
MongoDB | Blog
MongoDB | Blog
C
Cybersecurity and Infrastructure Security Agency CISA
N
News and Events Feed by Topic
Google Online Security Blog
Google Online Security Blog
H
Help Net Security
Spread Privacy
Spread Privacy
T
Threat Research - Cisco Blogs
GbyAI
GbyAI
I
Intezer
Application and Cybersecurity Blog
Application and Cybersecurity Blog
M
MIT News - Artificial intelligence
Vercel News
Vercel News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
IT之家
IT之家
MyScale Blog
MyScale Blog
腾讯CDC

博客园 - hq5460

一个C#的语法糖 .NET Reflector,SQL Prompt各种破解方法及详细步骤 Total Commander快捷键分类整理大全 C#中HttpClient的使用小结 SQL Server日期计算(使用DATEADD和DATEDIFF函数) MongoDB Sharding 机制分析 avalonJS入门 Ext JS 6学习文档-第8章-主题和响应式设计 Ext JS 6学习文档-第7章-图表 Ext JS 6学习文档-第5章-表格组件(grid) Ext JS 6学习文档-第4章-数据包 Ext JS 6学习文档-第3章-基础组件 Ext JS 6学习文档–第2章–核心概念 Ext JS 6学习文档–第1章–ExtJS入门指南 Console命令详解,让调试js代码变得更简单 使用Node.js+Socket.IO搭建WebSocket实时应用 node.js应用--转载 Node.js 究竟是什么? windbg内核诊断方式--转载
Ext JS 6学习文档-第6章-高级组件
hq5460 · 2016-08-24 · via 博客园 - hq5460

高级组件

本章涵盖了高级组件,比如 tree 和 data view。它将为读者呈现一个示例项目为 图片浏览器,它使用 tree 和 data view 组件。以下是本章将要讨论的主题:

  • Trees
  • Data views
  • 拖放
  • 图片浏览器 — 一个示例项目

本章的主要目标是探索 tree panel 和 data view 并且使用他们来构建一个示例项目图片浏览器。图片浏览器的最终展示效果如下图。

这个项目中的最重要的组件是 tree panel 和 data view 。本项目中使用的组件和概念有:

  • tree panel
  • Data views
  • Model
  • store 和 rest 代理
  • 容器和布局
  • 引用
  • 事件处理
  • 过滤

除了 tree panel 和 data view 你已经在之前的章节中学习了所有的我们目前已用到的知识。所以在本章中,我们首先学习 tree panel 和 data view。

1

tree panel

这在 ExtJS 中是一个非常强大且常用的组件,你可以使用它构建任意类型的树。一个 tree panel 是一个树形结构的具有层次化数据的UI。

它和 Ext.grid.Panel 相似, Ext.tree.Panel 也继承自Ext.panel.Table 。所以,它也是支持多列的。

和 grid panel 不同的是,tree panel 需要一个 tree store (Ext.Store.TreeStore)。 tree store 具有一些 tree panel 的功能所需使用的特殊的属性。

基本的 tree

我们来用一个简单的例子演示。tree panel 至少需要一个 tree store 来提供数据。我们首先来创建 tree 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

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 

Ext.create('Ext.tree.Panel', {  

title: 'Basic Tree',  

width: 200,  

height: 450,  

store: store,

rootVisible: true,  

renderTo: Ext.getBody()

});

下列截图为以上代码的输出结果:

1

现在,我们创建一个高级点的树,它是可以拖拽的。同时还需要用到 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 节点之下:

1

tree grid

你可以将多个列添加到 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 的输出结果:

 1

Data views

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 文件才行:

<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font- awesome/4.3.0/css/font-awesome.min.css">

一下代码创建了一个 data view,并且它指定了使用的数据源 store ,template 和 itemSelector :

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 ,等等,以上代码已经添加了监听,下列是输出结果:

 1

图片浏览器 – 一个示例项目

惯例,我们将用一个示例项目来回顾本章所学,下面是示例项目的最终设计效果:

1

通过查看这个设计,你会看到我们使用的最重要的组件就是 tree panel 和 data view 。它们如何使用和一些概念已经在本章的前面部分提及。

我们看看, 项目的目录结构。

1

下列视图代码是本项目的重要部分。这个视图呈现了应用中大部分可视组件。它使用 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 的代码在这儿。

  • 注意:当你不指定 model 的字段类型时,将会自动猜测类型。

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 为可拖拽的Configure the items as draggable
  • 创建放置目标
  • 完成放置目标

配置 item 为可拖拽的

想要拖拽一个 item ,你需要为每一个元素创建 Ext.dd.DD 实例。

查看下列代码,通过创建 Ext.dd.DD 让所有使用 pics 类的 div 元素成为可拖拽的:

// 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 元素创建放置目标:

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) ,如以下代码所示:

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。最后结合所学创建了一个示例项目。