上一篇文章我们已经为项目添加了header,接下来修改左侧导航栏为树(treepanel)。
View/main目录下建立Navigation.js
Ext.define('MyApp.view.main.Navigation', {
extend: 'Ext.tree.Panel',//继承treepanel
xtype: 'app-navigation',
rootVisible: false,
useArrows: true,
hideHeaders: true,
width: 250,
minWidth: 100,
split: true,
collapsible: true
});
在view/main/Main.js中引入Navigation.js并使用
Ext.define('MyApp.view.main.Main', {
extend: 'Ext.container.Container',
requires: [
'MyApp.view.main.MainController',
'MyApp.view.main.MainModel',
'MyApp.view.main.Header',//引入Header
'MyApp.view.main.Navigation'//引入导航栏
],
xtype: 'app-main',
controller: 'main',
viewModel: {
type: 'main'
},
layout: {
type: 'border'
},
items: [
{
region: 'north',
xtype: 'app-header'//使用Header
}, {
xtype: 'app-navigation',
region: 'west'
}, {
region: 'center',
xtype: 'tabpanel',
items: [{
title: 'Tab 1',
html: 'Content appropriate for the current navigation.
'
}]
}]
});
效果图
接下来为treepanel加入节点。我们只需创建一个treestore,并引入到treepanel下就可以创建出树节点。树节点有叶子节点和非叶子节点(父节点),不同的节点在treestore中的属性设置是不一样的,我们可以看一下简单的treestore。
Ext.create('Ext.data.TreeStore', {
root: {
expanded: true,
children: [
{text: "节点一", id: "danqun", leaf: false},
{text: "节点二", id: "jinyinguanli", leaf: true},
{text: "节点三", id: "gongchenxiangmu", leaf: true}
]
}
})
在treepanel中显示的节点就是由children中的内容来的,参数简单易懂,text就是节点显示的名称,id就是节点的id,leaf就是是否是叶子节点。我们把这个store加入到Navigation.js中看看效果。在Navigation.js加入以下代码
store:Ext.create('Ext.data.TreeStore', {
root: {
expanded: true,
children: [
{text: "节点一", id: "danqun", leaf: false},
{text: "节点二", id: "jinyinguanli", leaf: true},
{text: "节点三", id: "gongchenxiangmu", leaf: true}
]
}
})
效果图
下面我们编写正式使用的treestore数据。正式使用时,我们就不直接在view层里面使用stroe了,我们把store建在store层里面,并且数据远程获取。由于这里没涉及到后台,所以获取的数据为建立在我们当前项目中的模拟数据,如果有和后台结合时,只需把store中的url改成后台获取数据的地址即可,当然,数据的格式要和我们的模拟数据保持一致。
在store文件夹中建立main文件夹,在main文件夹下创建Navigation.js
Ext.define('MyApp.store.main.Navigation', {
extend: 'Ext.data.TreeStore',
alias: 'store.navigation',
proxy: {
type: 'ajax',
url: 'resources/data/Navigation.json'
},
root: {
expanded: true
},
autoLoad: true
});
观察一下我们可发现这一行代码url: 'resources/data/Navigation.json',意思为获取指定目录下的json数据,所以下一步,我们应该在resources目录下建立data包,data包下再建立Navigation.json文件。
当然,Navigation.json文件你可以随便放在任何目录下,名字也可以任意修改,只要在使用时url路径别写错就好了。看一下Navigation.json的内容
[
{
text: 'Panels',
id: 'panels',
expanded: true,
children: [
{
id: 'basic-panels',
text: 'Basic Panel',
leaf: true
},
{
id: 'framed-panels',
text: 'Framed Panel',
leaf: true
},
{
id: 'panel-header-position',
text: 'Header Positioning',
leaf: true
}
]
},
{
text: 'Grids',
id: 'grids',
expanded: true,
children: [
{
id: 'array-grid',
text: 'Array Grid',
leaf: true
},
{
id: 'grouped-grid',
text: 'Grouped Grid',
leaf: true
},
{
id: 'locking-grid',
text: 'Locking Grid',
leaf: true
},
{
id: 'grouped-header-grid',
text: 'Grouped Header Grid',
leaf: true
},
{
id: 'multi-sort-grid',
text: 'Multiple Sort Grid',
leaf: true
},
{
id: 'progress-bar-pager',
text: 'Progress Bar Pager',
leaf: true
},
{
id: 'sliding-pager',
text: 'Sliding Pager',
leaf: true
},
{
id: 'xml-grid',
text: 'XML Grid',
leaf: true
},
{
id: 'paging-grid',
text: 'Paging',
leaf: true
},
{
id: 'grid-plugins',
text: 'Grid Plugins',
leaf: true
},
{
id: 'grid-filtering',
text: 'Grid Filtering',
leaf: true
},
{
id: 'reconfigure-grid',
text: 'Reconfigure Grid',
leaf: true
},
{
id: 'property-grid',
text: 'Property Grid',
leaf: true
},
{
id: 'cell-editing',
text: 'Cell Editing',
leaf: true
},
{
id: 'row-expander-grid',
text: 'Row Expander',
leaf: true
},
{
id: 'big-data-grid',
text: 'Big Data',
leaf: true
},
{
id: 'widget-grid',
text: 'Widget grid',
leaf: true
},
{
id: 'customer-grid',
text: 'Customer/Order grid',
leaf: true
}
]
},
{
text: 'Data Binding',
id: 'data-binding',
expanded: true,
children: [
{
id: 'binding-hello-world',
text: 'Hello World',
leaf: true
},
{
id: 'binding-dynamic',
text: 'Dynamic',
leaf: true
},
{
id: 'binding-two-way',
text: 'Two Way',
leaf: true
},
{
id: 'binding-formulas',
text: 'Formulas',
leaf: true
},
{
id: 'binding-associations',
text: 'Associations',
leaf: true
},
{
id: 'binding-component-state',
text: 'Component State',
leaf: true
},
{
id: 'binding-chained-stores',
text: 'Chaining Stores',
leaf: true
},
{
id: 'binding-combo-chaining',
text: 'Chained ComboBoxes',
leaf: true
},
// { id: 'binding-gridform', text: 'Grid + Form', leaf: true },
{
id: 'binding-model-validation',
text: 'Model Validation',
leaf: true
},
{
id: 'binding-field-validation',
text: 'Field Validation',
leaf: true
},
{
id: 'binding-two-way-formulas',
text: 'Two-Way Formulas',
leaf: true
},
{
id: 'binding-slider-form',
text: 'Slider and Form Fields',
leaf: true
},
{
id: 'binding-child-session',
text: 'Isolated Child Sessions',
leaf: true
}
]
},
{
text: 'Trees',
id: 'trees',
expanded: true,
children: [
{
id: 'basic-trees',
text: 'Basic Trees',
leaf: true
},
{
id: 'tree-reorder',
text: 'Tree Reorder',
leaf: true
},
{
id: 'tree-grid',
text: 'Tree Grid',
leaf: true
},
{
id: 'tree-two',
text: 'Two Trees',
leaf: true
},
{
id: 'check-tree',
text: 'Check Tree',
leaf: true
},
{
id: 'tree-xml',
text: 'XML Tree',
leaf: true
},
{
id: 'filtered-tree',
text: 'Filtered Tree',
leaf: true
},
{
id: 'heterogeneous-tree',
text: 'Heterogeneous Tree',
leaf: true
}
]
},
{
text: 'Tabs',
id: 'tabs',
expanded: true,
children: [
{
id: 'basic-tabs',
text: 'Basic Tabs',
leaf: true
},
{
id: 'plain-tabs',
text: 'Plain Tabs',
leaf: true
},
{
id: 'framed-tabs',
text: 'Framed Tabs',
leaf: true
},
{
id: 'icon-tabs',
text: 'Icon Tabs',
leaf: true
},
{
id: 'ajax-tabs',
text: 'Ajax Tabs',
leaf: true
},
{
id: 'advanced-tabs',
text: 'Advanced Tabs',
leaf: true
},
{
id: 'navigation-tabs',
text: 'Navigation Tabs',
leaf: true
},
{
id: 'side-navigation-tabs',
text: 'Side Navigation Tabs',
leaf: true
},
{
id: 'header-tabs',
text: 'Header Tabs',
leaf: true
},
{
id: 'reorderable-tabs',
text: 'Reorderable Tabs',
leaf: true
}
]
},
{
text: 'Windows',
id: 'windows',
expanded: true,
children: [
{
id: 'basic-window',
text: 'Basic Window',
leaf: true
},
{
id: 'message-box',
text: 'Message Box',
leaf: true
}
]
},
{
text: 'Buttons',
id: 'buttons',
expanded: true,
children: [
{
id: 'basic-buttons',
text: 'Basic Buttons',
leaf: true
},
{
id: 'toggle-buttons',
text: 'Toggle Buttons',
leaf: true
},
{
id: 'menu-buttons',
text: 'Menu Buttons',
leaf: true
},
{
id: 'menu-bottom-buttons',
text: 'Menu Bottom Buttons',
leaf: true
},
{
id: 'split-buttons',
text: 'Split Buttons',
leaf: true
},
{
id: 'split-bottom-buttons',
text: 'Split Bottom Buttons',
leaf: true
},
{
id: 'left-text-buttons',
text: 'Left Text Buttons',
leaf: true
},
{
id: 'right-text-buttons',
text: 'Right Text Buttons',
leaf: true
},
{
id: 'link-buttons',
text: 'Link Buttons',
leaf: true
},
{
id: 'segmented-buttons',
text: 'Segmented Buttons',
leaf: true
},
{
id: 'vertical-segmented-buttons',
text: 'Vertical Segmented Buttons',
leaf: true
}
]
},
{
text: 'DataView',
id: 'data-view',
expanded: true,
children: [
{
id: 'dataview-multisort',
text: 'Multisort DataView',
leaf: true
}
]
},
{
text: 'Form Fields',
id: 'form-fields',
expanded: true,
children: [
{
id: 'form-number',
text: 'Number Field',
leaf: true
},
{
id: 'form-date',
text: 'Date/Month Picker',
leaf: true
},
{
id: 'form-combos',
text: 'Combo Boxes',
leaf: true
},
{
id: 'form-fileuploads',
text: 'File Uploads',
leaf: true
},
{
id: 'form-fieldreplicator',
text: 'Field Replicator',
leaf: true
},
{
id: 'form-grid',
text: 'Form with Grid',
leaf: true
},
{
id: 'form-tag',
text: 'Tag Field',
leaf: true
},
{
id: 'multi-selector',
text: 'Multi-Selector Grid',
leaf: true
},
{
id: 'form-fieldtypes',
text: 'Field Types',
leaf: true
},
{
id: 'form-fieldcontainer',
text: 'Field Container',
leaf: true
},
{
id: 'form-checkboxgroup',
text: 'Checkbox Groups',
leaf: true
},
{
id: 'form-radiogroup',
text: 'Radio Groups',
leaf: true
},
{
id: 'slider-field',
text: 'Slider Field',
leaf: true
}
]
},
{
text: 'Forms',
id: 'forms',
expanded: true,
children: [
{
id: 'form-login',
text: 'Login Form',
leaf: true
},
{
id: 'form-contact',
text: 'Contact Form',
leaf: true
},
{
id: 'form-register',
text: 'Register Form',
leaf: true
},
{
id: 'form-checkout',
text: 'Checkout Form',
leaf: true
},
{
id: 'form-vboxlayout',
text: 'VBox Layout',
leaf: true
},
{
id: 'form-hboxlayout',
text: 'HBox Layout',
leaf: true
},
{
id: 'form-multicolumn',
text: 'Multi Column Form',
leaf: true
},
{
id: 'form-xml',
text: 'XML Form',
leaf: true
},
{
id: 'form-advtypes',
text: 'Custom VTypes',
leaf: true
},
{
id: 'form-customfields',
text: 'Custom fields',
leaf: true
},
{
id: 'form-forumsearch',
text: 'Forum Search',
leaf: true
},
{
id: 'form-customerrors',
text: 'Custom Error Handling',
leaf: true
}
]
},
{
text: 'Toolbars',
id: 'toolbars',
expanded: true,
children: [
{
id: 'basic-toolbar',
text: 'Basic Toolbar',
leaf: true
},
{
id: 'docked-toolbars',
text: 'Docked Toolbar',
leaf: true
},
{
id: 'breadcrumb-toolbar',
text: 'Breadcrumb Toolbar',
leaf: true
}
]
},
{
text: 'Layouts',
id: 'layouts',
expanded: true,
children: [
{
id: 'layout-absolute',
text: 'Absolute Layout',
leaf: true
},
{
id: 'layout-accordion',
text: 'Accordion Layout',
leaf: true
},
{
id: 'layout-border',
text: 'Border Layout',
leaf: true
},
{
id: 'layout-card',
text: 'Card Layout',
leaf: true
},
{
id: 'layout-cardtabs',
text: 'Card (Tabs)',
leaf: true
},
{
id: 'layout-center',
text: 'Center Layout',
leaf: true
},
{
id: 'layout-column',
text: 'Column Layout',
leaf: true
},
{
id: 'layout-fit',
text: 'Fit Layout',
leaf: true
},
{
id: 'layout-horizontal-box',
text: 'HBox Layout',
leaf: true
},
{
id: 'layout-table',
text: 'Table Layout',
leaf: true
},
{
id: 'layout-vertical-box',
text: 'VBox Layout',
leaf: true
}
]
},
{
text: 'Drag & Drop',
id: 'drag-drop',
expanded: true,
children: [
{
id: 'dd-field-to-grid',
text: 'Field to Grid',
leaf: true
},
{
id: 'dd-grid-to-form',
text: 'Grid to Form',
leaf: true
},
{
id: 'dd-grid-to-grid',
text: 'Grid to Grid',
leaf: true
}
]
},
{
text: 'Enterprise',
id: 'enterprise',
expanded: true,
children: [
{
id: 'amf-grid',
text: 'AMF Grid',
leaf: true
},
{
id: 'soap-grid',
text: 'Soap Grid',
leaf: true
}
]
}
]
各个字段的意思我们前面已经解释过了,如果是跟后台结合,那么后台传过来的数据,就应该和上面的json数据格式一样,这样才能生成树节点。
接下来把treestore引入到treepanel中。我们的项目是MVVM结构,数据不直接写入到view中,而是绑定到viewmodel中,所以我们在MainModel.js中引入treestore,然后在treepanel中,只要绑定MainModel中的store即可。
修改view/main/MainModel.js
Ext.define('MyApp.view.main.MainModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.main',
requires:['MyApp.store.main.Navigation'],//引入必要文件
data: {
navigationTitle: '导航栏'//导航栏标题
},
stores:{
navigationStore:{
type:'navigation'//导航栏treestore
}
}
});
修改view/main/Navigation.js
Ext.define('MyApp.view.main.Navigation', {
extend: 'Ext.tree.Panel',//继承treepanel
xtype: 'app-navigation',
rootVisible: false,
useArrows: true,
hideHeaders: true,
width: 250,
minWidth: 100,
split: true,
collapsible: true,
bind: {
store: '{navigationStore}',//绑定store
title: '{navigationTitle}'
}
});
这样就把数据绑定到treepanel中了,看看效果
至此就完成了左边导航栏。下一篇文章处理左侧导航栏的点击事件。
另外,我也把这个项目托管在github上:https://github.com/likeadog/Extjs5.0Demo