[Ext JS 6 By Example 翻译] 第6章 - 高级组件

转载自:http://www.jeeboot.com/archives/1227.html


本章涵盖了高级组件,比如 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 并硬编码内置数据:

[javascript]  view plain  copy
  1. var store = Ext.create('Ext.data.TreeStore', {  
  2.     root: {       
  3.         expanded: true,       
  4.         text: 'Continents',  
  5.         children: [{         
  6.             text: 'Antarctica',         
  7.             leaf: true  
  8.         }, {  
  9.             text: 'South America',         
  10.             expanded: true,         
  11.             children: [{           
  12.                 text: 'Brazil',           
  13.                 leaf: true  
  14.             }, {           
  15.                 text: 'Chile',           
  16.                 leaf: true  
  17.             }]       
  18.         }, {         
  19.             text: 'Asia',         
  20.             expanded: true,         
  21.             children: [{           
  22.                 text: 'India',           
  23.                 leaf: true  
  24.             },{           
  25.                 text: 'China',           
  26.                 leaf: true  
  27.             }]       
  28.         }, {         
  29.             text: 'Africa',         
  30.             leaf: true  
  31.         }]     
  32.     }   
  33. });  

接着继续创建 Ext.tree.Panel :

[javascript]  view plain  copy
  1. Ext.create('Ext.tree.Panel', {     
  2.     title: 'Basic Tree',     
  3.     width: 200,     
  4.     height: 450,     
  5.     store: store,  
  6.     rootVisible: true,     
  7.     renderTo: Ext.getBody()   
  8. });  


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

1

现在,我们创建一个高级点的树,它是可以拖拽的。同时还需要用到 tree panel 和 tree store 的一些额外选项。拖拽只需要添加一个插件叫做 treeviewdragdrop 。如以下代码所示:

[javascript]  view plain  copy
  1. var store = Ext.create('Ext.data.TreeStore', {     
  2.     root: {       
  3.         expanded: true,       
  4.         text: 'Continents',  
  5.         checked: false,       
  6.         children: [{         
  7.             text: 'Antarctica',         
  8.             leaf: true ,         
  9.             checked: false  
  10.         },{  
  11.             text: 'South America',         
  12.             expanded: false,         
  13.             checked: true,         
  14.             children: [{           
  15.                 text: 'Chile',           
  16.                 leaf: true,  
  17.                 checked: true  
  18.             }]  
  19.         },{         
  20.             text: 'Asia',         
  21.             expanded: true,         
  22.             checked: true,         
  23.             children: [{           
  24.                 text: 'India',           
  25.                 leaf: true,           
  26.                 checked: true         
  27.             },{           
  28.                 text: 'China',           
  29.                 leaf: true,           
  30.                 checked: true  
  31.             }]  
  32.         },{         
  33.             text: 'Africa',         
  34.             leaf: true,         
  35.             checked: true  
  36.         }]  
  37.     }  
  38. });  
  39.    
  40. Ext.create('Ext.tree.Panel', {     
  41.     title: 'Basic Tree',     
  42.     width: 200,     
  43.     height: 450,     
  44.     store: store,     
  45.     rootVisible: true,     
  46.     useArrows: true,     
  47.     lines: false,     
  48.     renderTo: Ext.getBody(),     
  49.     viewConfig: {       
  50.         plugins: {         
  51.             ptype: 'treeviewdragdrop',         
  52.             containerScroll: true  
  53.         }  
  54.     }  
  55. });  


如以下截图所示的输出。我把节点  South America 拖拽至  Asia 节点之下:

1

tree grid

你可以将多个列添加到 tree ,同时也能创建 tree grid 。默认 tree 包含一列,用的是 tree store 中节点的文本字段。

在这个 store 中,你可以看到在每个节点上除了节点名称,还添加了一些其他的字段,这些字段用于在 tree panel 的列展示上。tree grid 的功能有例如 列调整,排序,过滤等等,以下是代码:

[javascript]  view plain  copy
  1. var store = Ext.create('Ext.data.TreeStore', {     
  2.     root: {       
  3.         expanded: true,       
  4.         text: 'Continents',       
  5.         children: [{         
  6.             name: 'Antarctica',         
  7.             population: 0,         
  8.             area: 14,         
  9.             leaf: true  
  10.         },{  
  11.             name: 'South America',         
  12.             population: 385 ,         
  13.             area: 17.84,         
  14.             expanded: false,         
  15.             children: [{           
  16.                 name: 'Chile',  
  17.                 population: 18,           
  18.                 area: 0.7,           
  19.                 leaf: true,  
  20.             }]  
  21.         },{         
  22.             name: 'Asia',         
  23.             expanded: true,         
  24.             population: 4164,         
  25.             area: 44.57,         
  26.             children: [{           
  27.                 name: 'India',           
  28.                 leaf: true,           
  29.                 population: 1210,           
  30.                 area: 3.2  
  31.             },{           
  32.                 name: 'China',           
  33.                 leaf: true,           
  34.                 population: 1357,           
  35.                 area: 9.5  
  36.             }]  
  37.         },{         
  38.             name: 'Africa',         
  39.             leaf: true,         
  40.             population: 1110,         
  41.             area: 30  
  42.         }]  
  43.     }  
  44. });  

以下的 grid 和上面的 tree panel 差不多一样,只是添加为多列了,这个 xtyp treecolumn 提供缩进和文件夹结构。像一个正常的 grid 一样,tree grid 的列可以是任意类型的例如 checkbox,picture,button,URL 等等。

默认列大小是可调整的,如果需要你也可以固定它的宽度。看下面的代码:

[javascript]  view plain  copy
  1. Ext.create('Ext.tree.Panel', {     
  2.     title: 'Tree Grid',     
  3.     width: 500,     
  4.     height: 450,     
  5.     store: store,     
  6.     rootVisible: false,     
  7.     useArrows: true,  
  8.     lines: false,     
  9.     scope: this,     
  10.     renderTo: Ext.getBody(),     
  11.     columns: [{       
  12.         xtype: 'treecolumn',       
  13.         text: 'Name',       
  14.         flex: 1,       
  15.         sortable: true,       
  16.         dataIndex: 'name'  
  17.     } , {      
  18.         text: 'Population (millons)',       
  19.         sortable: true,       
  20.         width: 150,       
  21.         dataIndex: 'population'  
  22.     } , {      
  23.         text: 'Area (millons km^2)',       
  24.         width: 150,       
  25.         sortable: true,       
  26.         dataIndex: 'area'  
  27.     }]  
  28. });  

这是上面 Tree Grid 的输出结果:

 1

Data views

Ext.view.View (xtype:dataview) 一个现实数据的自定义模板。你需要提供自定义的模板和数据源(store)。模板应该使用 Ext.XTemplate 。

data view 提供了内置的事件,例如 click,double-click,mouseover,mouseout,等等。

首先我们创建一个简单的 model 名为 Person ,还需要创建一个 store 并持有 Person 的列表,如以下代码所示:

[javascript]  view plain  copy
  1. Ext.define('Person', {  
  2.     extend : 'Ext.data.Model',  
  3.     fields : [ {  
  4.         name : 'name',  
  5.         type : 'string'  
  6.     }, {  
  7.         name : 'age',  
  8.         type : 'int'  
  9.     }, {  
  10.         name : 'gender',  
  11.         type : 'int'  
  12.     } ]  
  13. });  
  14.    
  15. Ext.create('Ext.data.Store', {  
  16.     id : 'employees',  
  17.     model : 'Person',  
  18.     data : [{  
  19.         name : 'Mike',  
  20.         age : 22,  
  21.         gender : 0  
  22.     },{  
  23.         name : 'Woo',  
  24.         age : 32,  
  25.         gender : 1  
  26.     },{  
  27.         name : 'John',  
  28.         age : 33,  
  29.         gender : 1  
  30.     },{  
  31.         name : 'Kalai',  
  32.         age : 25,  
  33.         gender : 0  
  34.     }]  
  35. });  

然后我们要来创建这个模板。下列模板使用 HTML 的 table 元素来呈现自定义格式的数据。

在模板中使用一个 model 的字段时,你可以使用花括号包括字段名的方式来使用它,例如:{fieldname}

XTemplate 支持有条件的展现和 if 语句,如以下代码所示:

[javascript]  view plain  copy
  1. var empTpl = new Ext.XTemplate(  
  2. '<tpl for=".">',  
  3.    '<div style="margin-bottom: 10px;" class="data-view">',  
  4.    '<table style="width:100%">',  
  5.      '<tr>',  
  6.        '<td style="font-size: 100px;width:100px;" rowspan="3"><i class="fa fa-user"></i></td>',           
  7.        '<td>Name: {name}< /td>',  
  8.      '</tr>',  
  9.        
  10.      '<tr>',  
  11.        '<td>Age:{age}< /td>',  
  12.      '</tr>',  
  13.        
  14.      '<tr>',  
  15.        '<td>Gender: <tpl if="gender == 1">',  
  16.          '<i class="fa fa-mars"></i>',  
  17.          '<tpl else>',  
  18.          '<i class="fa fa-venus"></i>',  
  19.          '</tpl></td>',  
  20.      '</tr></table> ',  
  21.    '</div>',  
  22. '</tpl>'  
  23. );  

看上面的例子,我使用了 awesome 字体图标的样式。你需要添加下列代码到你的 HTML 文件才行:

[html]  view plain  copy
  1. <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font- awesome/4.3.0/css/font-awesome.min.css">  

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

[javascript]  view plain  copy
  1. Ext.create('Ext.view.View', {  
  2.   store : Ext.getStore('employees'),  
  3.   tpl : empTpl,  
  4.   itemSelector : 'div.data-view',  
  5.   renderTo : Ext.getBody(),  
  6.   listeners : {  
  7.     itemclick : function(node, rec, item, index, e) {  
  8.       alert(rec.data.name);  
  9.     }  
  10.   }  
  11. });  

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 :

[javascript]  view plain  copy
  1. Ext.define('PE.view.pics.Pics', {  
  2.   extend : 'Ext.panel.Panel',  
  3.   /* Marks these are required classes to be to loaded before loading this view */  
  4.   requires : [ 'PE.view.pics.PicsController' ],  
  5.   xtype : 'app-pics',  
  6.   controller : 'pics',  
  7.   items : [ {  
  8.     xtype : 'container',  
  9.     layout : 'hbox',  
  10.     cls : 'pics-list',  
  11.     items : [ {  
  12.       xtype : 'treepanel',  
  13.       width : 200,  
  14.       height : '100%',  
  15.       store : 'albums',  
  16.       border : true,  
  17.       useArrows : true,  
  18.       cls : 'tree',  
  19.       rootVisible : false,  
  20.       listeners : {  
  21.         itemdblclick : 'onNodeSelect'  
  22.       },  
  23.       dockedItems : [ {  
  24.         xtype : 'toolbar',  
  25.         dock : 'top',  
  26.         ui : 'footer',  
  27.         items : [{  
  28.           xtype : 'component',  
  29.           flex : 1  
  30.         },{  
  31.           xtype : 'button',  
  32.           text : 'Upload',  
  33.           cls : 'btn-blue'  
  34.         }]  
  35.       }]  
  36.     },{  
  37.       xtype : 'dataview',  
  38.       reference : 'picsList',  
  39.       cls : 'pics-list-content',  
  40.       store : 'pics',  
  41.       tpl : [  
  42.              '<tpl for=".">',  
  43.              '<div class="thumb"><img src="{url}" title=""></div>',  
  44.              '</tpl>'  
  45.       ],  
  46.       multiSelect : true,  
  47.       minHeight : 400,  
  48.       flex : 1,  
  49.       trackOver : true,  
  50.       overItemCls : 'x-item-over',  
  51.       itemSelector : 'div.thumb',  
  52.       emptyText : 'No images to display'  
  53.     }]  
  54.   }]  
  55. });  

控制器 ViewController 里处理了 tree panel 的 itemdblclick 事件,只显示所选择节点下的图片。

还有一个 upload 按钮的 click 事件,这里是未处理的。额,这是你的作业啦。看看下列代码:

[javascript]  view plain  copy
  1. Ext.define('PE.view.pics.PicsController', {  
  2.   extend : 'Ext.app.ViewController',  
  3.   alias : 'controller.pics',  
  4.   views : [ 'PE.view.pics.Pics' ],  
  5.   requires : [ 'PE.store.Pics''PE.store.Albums' ],  
  6.   onNodeSelect : function(node, rec, item, index, e){  
  7.     var albums = [];  
  8.     albums.push(rec.id);  
  9.     rec.childNodes.forEach(function(item) {  
  10.       albums.push(item.id);  
  11.     });  
  12.    
  13.     Ext.getStore('pics').filter({  
  14.       property : 'albumId',  
  15.       operator : 'in',  
  16.       value : albums  
  17.     });  
  18.   }  
  19. });  


Model 和 Store 的代码在这儿。

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

[javascript]  view plain  copy
  1. Ext.define('Pic', {  
  2.   extend : 'Ext.data.Model',  
  3.   fields : [ 'id''url''albumId' ]  
  4. });  
  5.    
  6. Ext.define('PE.store.Pics', {  
  7.   extend : 'Ext.data.Store',  
  8.   storeId : 'pics',  
  9.   model : 'Pic',  
  10.   proxy : {  
  11.     type : 'rest',  
  12.     url : 'pics'// URL that will load data with respect to start and limit params  
  13.     reader : {  
  14.       type : 'json'  
  15.     }  
  16.   }  
  17. });  
  18.    
  19. Ext.create('PE.store.Pics').load();  
  20.    
  21. Ext.define('PE.store.Albums', {  
  22.   extend : 'Ext.data.TreeStore',  
  23.   storeId : 'albums',  
  24.   root : {  
  25.     expanded : true,  
  26.     children : [ {  
  27.       id : 100,  
  28.       text : ' California',  
  29.       expanded : true,  
  30.       children : [ {  
  31.         id : 600,  
  32.         text : ' Big Sur',  
  33.         leaf : true  
  34.       }, {  
  35.         id : 500,  
  36.         text : ' Yosemite',  
  37.         leaf : true  
  38.       }]  
  39.     }, {  
  40.       id : 400,  
  41.       text : ' Arizona',  
  42.       expanded : true,  
  43.       children : [ {  
  44.         id : 300,  
  45.         text : ' Horseshoe bend',  
  46.         leaf : true  
  47.       }]  
  48.     }, {  
  49.       id : 200,  
  50.       text : ' Home',  
  51.       leaf : true  
  52.     }, {  
  53.       id : 700,  
  54.       text : ' India',  
  55.       expanded : true,  
  56.       children : [ {  
  57.         id : 800,  
  58.         text : ' Ooty',  
  59.         leaf : true  
  60.       }, {  
  61.         id : 900,  
  62.         text : ' Chennai',  
  63.         leaf : true  
  64.       }, {  
  65.         id : 1000,  
  66.         text : ' Munnar',  
  67.         leaf : true  
  68.       } ]  
  69.     } ]  
  70.   }  
  71. });  
  72.    
  73. 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 元素成为可拖拽的:

[javascript]  view plain  copy
  1. // Configure the pics as draggable var pics = Ext.get('pics').select('div');  
  2. Ext.each(pics.elements, function(el) {  
  3.   var dd = Ext.create('Ext.dd.DD', el, ' picsDDGroup', {  
  4.     isTarget : false  
  5.   });  
  6. });  

创建放置目标

使用 Ext.dd.DDTarget 创建放置容器。以下代码为所有的使用 album 类的 div 元素创建放置目标:

[javascript]  view plain  copy
  1. var albums = Ext.get('album').select('div');  
  2. Ext.each(albums.elements, function(el) {  
  3.   var albumDDTarget = Ext.create('Ext.dd.DDTarget', el,  
  4.   'picsDDGroup');  
  5. });  

完成放置目标

当一个可拖拽项放置到一个放置容器,我们需要从这个 item 的源位置将它移动到目标位置。这通过覆盖 DD 的 onDragDrop 方法来实现。看一看下列代码:

[javascript]  view plain  copy
  1. var overrides = {  
  2.   onDragDrop : function(evtObj, targetElId) {  
  3.     var dropEl = Ext.get(targetElId);  
  4.     if (this.el.dom.parentNode.id != targetElId) {  
  5.       dropEl.appendChild(this.el);  
  6.       this.onDragOut(evtObj, targetElId);  
  7.       this.el.dom.style.position = '';  
  8.       this.el.dom.style.top = '';  
  9.       this.el.dom.style.left = '';  
  10.     } else {  
  11.       this.onInvalidDrop();  
  12.     }  
  13.   },  
  14.   onInvalidDrop : function() {  
  15.     this.invalidDrop = true;  
  16.   }  
  17. };  

因为 DD 元素已经是实例了,重写的方法需要应用 Ext.apply(dd, overrides) ,如以下代码所示:

[javascript]  view plain  copy
  1. var albums = Ext.get('album').select('div');  
  2. var pics = Ext.get('pics').select('div');  
  3. Ext.each(pics.elements, function(el) {  
  4.   var dd = Ext.create('Ext.dd.DD', el, ' picsDDGroup', {  
  5.     isTarget : false  
  6.   });  
  7.   Ext.apply(dd, overrides);  
  8. });  


总结

在本章中,你学习到如何使用拖拽功能。我们也看了几个高级组件:tree panel 和 data view。最后结合所学创建了一个示例项目。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值