Ext JS 6学习文档-第6章-高级组件

高级组件本章涵盖了高级组件,比如 tree 和 data view。它将为读者呈现一个示例项目为 图片浏览器,它使用 tree 和 data view 组件。以下是本章将要讨论的主题:
  • Trees
  • Data views
  • 拖放
  • 图片浏览器 — 一个示例项目
  • http://www.jeeboot.com/archives/1227.html本章的主要目标是探索 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 :
     
     
    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()
    });
     下列截图为以上代码的输出结果: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 节点之下:1tree 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 viewsExt.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 ,等等,以上代码已经添加了监听,下列是输出结果: 1 图片浏览器 – 一个示例项目惯例,我们将用一个示例项目来回顾本章所学,下面是示例项目的最终设计效果:1通过查看这个设计,你会看到我们使用的最重要的组件就是 tree panel 和 data view 。它们如何使用和一些概念已经在本章的前面部分提及。 我们看看, 项目的目录结构。
  • 完整的源码在这里 https://github.com/ananddayalan/extjs-byexample-picture-explorer
  • 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 元素成为可拖拽的:
     
     
    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。最后结合所学创建了一个示例项目。

    相关内容推荐