目录
目录
一、开发一个“商家订单”的功能~~ 效果图
二、开发架构 -- MVVM
【what】
Model–View–ViewModel(MVVM) 是一个软件架构设计模式,由微软 WPF 和 Silverlight 的架构师 Ken Cooper 和 Ted Peters 开发,是一种简化用户界面的事件驱动编程方式。由 John Gossman(同样也是 WPF 和 Silverlight 的架构师)于2005年在他的博客上发表。
三、开发思路 - - MVVM
上一篇给大家演示了 反向思路,这次的话给大家演示正向思路,
正向思路:也就是从0开始开发,当我需要什么组件的时候就去开发使用什么组件。
first:订单模块主视图,因此需要一个主视图组件。— — Order.js
second:主视图中,放一个表格,因此需要一个表格组件。表格的column跟bbar跟Grid写在一个文件中 — — OrderGrid.js
third:GrId需要显示数据,因此需要一个数据源Store -- OrderStore.js
four:而我们的Store数据源需要一个Model — — OrderModel.js
five:这一步很重要,就是将我们的数据绑定到ViewModel上,这一步是我们之前MVC架构没有的操作,参考下面的代码:
/**
1.绑定到主视图
2.通过bind属性绑定到具体的子视图
8*/
Ext.define('Admin.view.order.OrderViewModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.orderViewModel',
stores: {
orderLists: {
type: 'orderStore',//Store reference ==Store的属性 alias: 'store.orderStore',
autoLoad: true //Auto load
}
}
});
//在主视图中,Grid.js
bind:'{orderLists}',
six:表格上面需要一个查询表单 — — OrderGridQueryForm.js
seven:查询触发函数,因此需要一个控制器 — — OrderViewController.js
eight:添加数据需要弹出一个外框组件 — — OrderGridWindow.js
nine :弹窗组件中放入一个 表单 — — OrderGridForm.js
综上所述:九个步骤即可开发出这个模块
四、开发代码 ~~ 以下采用MVVM分层的开发模式。
first:订单模块主视图,因此需要一个主视图组件。— — Order.js
/**
*订单模块主视图
在主视图配置viewController和viewModel,
那么主视图的子视图也可以访问配置好viewController和viewModel。
*/
Ext.define('Admin.view.order.Order', { //1.修改文件路径
extend: 'Ext.container.Container', //2.继承的组件类型
//3.重写继承组件的属性:
xtype: 'order',
//这是第seven步骤开发的控制器,通过以下的开发进行绑定
controller: 'orderViewController', //视图绑定viewController
//这是第five步骤开发的ViewModel,将viewModel绑定到主视图
viewModel : {type: 'orderViewModel'}, //视图绑定viewModel
layout:'fit',
margin: '20 20 20 20',
items: [{
//这是第二步骤开发的表格组件
xtype: 'orderGrid'
}]
});
second:主视图中,放一个表格,因此需要一个表格组件。表格的column跟bbar跟Grid写在一个文件中 — — OrderGrid.js
/**
*订单模块子视图
*/
Ext.define('Admin.view.order.OrderGrid', { //1.修改文件路径
extend: 'Ext.grid.Panel', //2.继承的组件类型
//3.重写继承组件的属性:
xtype: 'orderGrid',
id:'orderGrid',
title:'<b>订单列表</b>',
selModel: Ext.create('Ext.selection.CheckboxModel'),
bind:'{orderLists}',
dockedItems: [{
xtype: 'toolbar',
dock: 'top',
items: [Ext.apply({xtype: 'orderGridQueryForm'})]
}],
columns: [
{text: 'ID' ,sortable:true ,dataIndex:'orderId',hidden:true},
{text: '订单编号' ,sortable:true ,dataIndex:'orderNumber' ,width:100},
{text: '创建时间' ,sortable:true ,dataIndex:'createTime' ,width:160
,renderer: Ext.util.Format.dateRenderer('Y/m/d H:i:s')},
{text: '优先级',sortable:true ,dataIndex:'level' ,width:75},
{text: '供应商ID' ,sortable:true ,dataIndex:'supplierId',hidden:true},
{text: '供应商名称' ,sortable:false ,dataIndex:'suppName' ,width:120},
{text: '商品编号' ,sortable:false ,dataIndex:'pid' ,hidden:true},
{text: '商品名称' ,sortable:false ,dataIndex:'pname' ,width:120},
{text: '商品数量' ,sortable:true ,dataIndex:'pnumber' ,width:75},
{text: '商品单价' ,sortable:false ,dataIndex:'cost' ,width:75},
{text: '总价格' ,sortable:false ,dataIndex:'totalPrice' ,width:130},
{text: '是否入库' ,sortable:false ,dataIndex:'isIncomeStyle' ,flex:1}
],
// paging bar on the bottom
bbar: Ext.create('Ext.PagingToolbar', {
bind:'{orderLists}',
displayInfo: true,
displayMsg: 'Displaying topics {0} - {1} of {2}',
emptyMsg: "No topics to display",
items:['-', {
//xtype:'button',
text: '新建订单',
iconCls: 'x-fa fa-plus',
handler: 'orderGridOpenAddWindow'//绑定OrderViewController中的事件
},
{
//xtype:'button',
text: '修改订单',
iconCls: 'x-fa fa-undo',
handler: 'orderGridOpenEditWindow'//绑定OrderViewController中的事件
}
,
{
//xtype:'button',
text: '删除订单',
iconCls: 'x-fa fa-trash ',
handler: 'orderGridDeleteDate'//绑定OrderViewController中的事件
},
{
//xtype:'button',
text: '导出订单',
iconCls: 'fa fa-share-alt',
handler: 'orderGridExportXls'//绑定OrderViewController中的事件
}]
})
});
third:GrId需要显示数据,因此需要一个数据源Store -- OrderStore.js
Ext.define('Admin.store.order.OrderStore', {
extend: 'Ext.data.Store',
alias: 'store.orderStore', //1.Store取别名(reference)
model: 'Admin.model.order.OrderModel',//2.设置model的全路径
//data:{
// 'items':[
// { 'orderId': 1, 'orderNumber': 'od0000001', "createTime":"2017/9/8 16:35:00", "level":"高" , 'goodsId' :10001, 'goodsName' :'A', 'goodsNum' :'50', 'goodsPrice' :220, 'totalPrice' :1100},
// { 'orderId': 2, 'orderNumber': 'od0000002', "createTime":"2017/9/8 16:35:00", "level":"中", 'goodsId' :10002, 'goodsName' :'B', 'goodsNum' :'40', 'goodsPrice' :50, 'totalPrice' :2000},
// { 'orderId': 3, 'orderNumber': 'od0000099', "createTime":"2017/9/8 16:35:00", "level":"中" , 'goodsId' :10003, 'goodsName' :'C', 'goodsNum' :'30', 'goodsPrice' :150, 'totalPrice' :4500},
// { 'orderId': 4, 'orderNumber': 'od0000100', "createTime":"2017/9/8 16:35:00", "level":"低" , 'goodsId' :10004, 'goodsName' :'D', 'goodsNum' :'20', 'goodsPrice' :100, 'totalPrice' :2200}
// ]
//},
proxy: {
//type: 'memory',
type: 'ajax',
url: 'order/findPage.json',
reader: {
type: 'json',
//rootProperty: 'items'
rootProperty: 'content',
totalProperty: 'totalElements'
},
simpleSortMode:true
},
pageSize: 14,
autoLoad: true,
remoteSort: true,//全局排序
sorters: {
direction: 'DESC',
property: 'createTime'
}
});
four:而我们的Store数据源需要一个Model — — OrderModel.js.
Ext.define('Admin.model.order.OrderModel', {
extend: 'Admin.model.Base',
fields: [
{name:'orderId' ,type: 'int'},
{name:'orderNumber' ,type: 'string'},
{name:'createTime' ,type: 'date'},
{name:'level' ,type: 'string'},
{name:'supplierId' ,type: 'int'},
{name:'suppName' ,type: 'string'},
// {name:'goodsId' ,type: 'int'},
// {name:'goodsName' ,type: 'string'},
{name:'pnumber' ,type: 'int'},
// {name:'goodsPrice' ,type: 'float'},
{name:'totalPrice' ,type: 'float'}
]
});
five:这一步很重要,就是将我们的数据绑定到ViewModel上,
/**
1.绑定到主视图
2.通过bind属性绑定到具体的子视图
8*/
Ext.define('Admin.view.order.OrderViewModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.orderViewModel',
stores: {
orderLists: {
type: 'orderStore',//Store reference ==Store的属性 alias: 'store.orderStore',
autoLoad: true //Auto load
}
}
});
six:表格上面需要一个查询表单 — — OrderGridQueryForm.js
Ext.define('Admin.view.order.OrderGridQueryForm', {
extend: 'Ext.form.Panel',
alias: 'widget.orderGridQueryForm',
id:'myOrderGridQueryForm',
requires: [
'Ext.button.Button',
'Ext.form.field.Text',
'Ext.form.field.File',
'Ext.form.field.HtmlEditor',
'Ext.form.field.TextArea',
'Ext.form.field.Time',
'Ext.form.field.ComboBox',
'Ext.form.field.Date',
'Ext.form.field.Radio',
'Ext.form.field.Hidden'
],
//viewModel: {type: 'emailcompose'},
//cls: 'email-compose',
controller: 'orderViewController',
layout: {
type:'hbox',
align:'stretchmax'
},
bodyPadding: 0,
scrollable: false,
defaults: {
labelWidth: 65,
labelSeparator: ':'
},
items:[{
xtype: 'textfield',
fieldLabel: '订单编号',
reference: 'orderSearchForm-orderNumber',
name:'orderNumber',
//allowBlank : false,
padding:4
},{
xtype: 'datefield',
format: 'Y/m/d H:i:s',
fieldLabel: '创建时间',
editable:true,
reference: 'orderSearchForm-createTime',
name:'createTime',
padding:4
,width:250
},{
xtype: 'combobox',
reference: 'orderSearchForm-isIncome',
editable:false,
fieldLabel: '是否入库',
name:'isIncome',
padding:4,
store: Ext.create('Ext.data.Store', {
fields: ['value', 'name'],
data : [
{"value":1, "name":"已入库"},
{"value":0, "name":"未入库"}
]
}),
queryMode: 'local',
displayField: 'name',
valueField: 'value'
},{
xtype: 'combobox',
reference: 'orderSearchForm-level',
editable:false,
fieldLabel: '优先级',
name:'level',
padding:4,
store: Ext.create('Ext.data.Store', {
fields: ['value', 'name'],
data : [
{"value":"HIGH", "name":"高"},
{"value":"MEDIUM", "name":"中"},
{"value":"LOW", "name":"低"}
]
}),
queryMode: 'local',
displayField: 'name',
valueField: 'value'
},{
xtype: 'button',
ui: 'gray',
margin:5,
//align:'right',
iconCls: 'x-fa fa-search',
text: '查询',
handler: 'orderSearchFormSubmit'
}
,{
xtype: 'button',
ui: 'gray',
margin:5,
//align:'right',
iconCls: 'x-fa fa-search',
text: '置空',
handler: function() {
this.up('form').getForm().reset();
var store = this.up('gridpanel').getStore();
Ext.getCmp('orderGrid').store.getProxy().extraParams ={
};
store.reload();
//Ext.getCmp('orderGrid').store.getProxy().url = 'order/findPage';
}
}
],
//,{
// xtype: 'textfield',
// fieldLabel: 'GoodsId',
// name:'goodsId'
//}
//,{
// xtype: 'textfield',
// fieldLabel: 'GoodsName',
// name:'goodsName'
//}
//,{
// xtype: 'textfield',
// fieldLabel: 'GoodsNum',
// name:'goodsNum'
//}
//,{
// xtype: 'textfield',
// fieldLabel: 'GoodsPrice',
// name:'goodsPrice'
//}
/* bbar: {
items: ['->',{
xtype: 'button',
//ui: 'soft-red',
text: '查询',
handler: ''
},{
xtype: 'button',
//ui: 'gray',
text: '取消',
handler: ''
}]
}
*/
});
seven:查询触发函数,因此需要一个控制器 CURD代码都在里面— — OrderViewController.js
Ext.define('Admin.view.order.OrderViewController', {
extend: 'Ext.app.ViewController',
alias: 'controller.orderViewController',
orderGridOpenAddWindow: function(btn) {
var cfg = Ext.apply({
xtype: 'orderGridWindow',
items: [Ext.apply({xtype: 'orderGridForm'})]
},{
title:'创建订单'//,width: 800//,height: 600
});
Ext.create(cfg);
},
orderGridFormSubmit: function(btn) {
var orderGridForm = btn.up('form').getForm();
var win = btn.up('window');
orderGridForm.submit( {
//waitTitle : '请稍后...',
//waitMsg : '正在保存订单信息,请稍后...',
url : 'order/saveOrUpdate',
method : 'post',
success : function(form, action) {
Ext.Msg.alert("提示",action.result.msg);
win.close();
//必须OrderGrid中增加对应id:'orderGrid'属性
Ext.getCmp('orderGrid').store.reload();
},
failure : function(form, action) {
win.close();
Ext.Msg.alert("提示",action.result.msg);
}
});
},
orderGridWindowClose: function(btn) {
var win = btn.up('window');
if(win){
win.close();
}
},
orderGridOpenEditWindow: function(btn) {
var grid = btn.up('gridpanel');//获取Grid视图
var selModel = grid.getSelectionModel();//获取Grid的SelectionModel
if (selModel.hasSelection()) {//判断是否选中记录
var record = selModel.getSelection()[0];//获取选中的第一条记录
//创建修改window和form
var orderGridWindow = Ext.widget('orderGridWindow',{
title:'修改订单',
items: [{xtype: 'orderGridForm'}]
});
//让form加载选中记录
orderGridWindow.down("form").getForm().loadRecord(record);
}else{
Ext.Msg.alert('提示',"请选择一行数据进行修改!");
}
},
orderGridDeleteDate: function(btn) {
var grid = btn.up('gridpanel');
var selModel = grid.getSelectionModel();
if (selModel.hasSelection()) {
Ext.Msg.confirm("警告", "确定要删除吗?", function (button) {
if (button == "yes") {
var selected = selModel.getSelection();
var selectIds = []; //要删除的id
Ext.each(selected, function (record) {
//alert(record.data.orderId);
selectIds.push(record.data.orderId);
})
Ext.Ajax.request({
url : 'order/deleteByIds',
method : 'post',
params : {
ids:selectIds
},
success: function(response, options) {
var json = Ext.util.JSON.decode(response.responseText);
if(json.success){
Ext.Msg.alert('操作成功', json.msg);
grid.getStore().reload();
}else{
Ext.Msg.alert('操作失败', json.msg);
}
}
});
}
});
}else{
Ext.Msg.alert('提示',"请选择一行数据进行删除!");
}
},
orderSearchFormSubmit:function(btn){
var store = btn.up('gridpanel').getStore();
//2.按照所选字段进行查询参数(条件)的扩展
var formValues=btn.up('form').getForm().getValues();
// alert(formValues["createTime"]);
// alert(formValues["orderNumber"]);
//alert(formValues["level"]);
if (formValues["createTime"]==''&&formValues["orderNumber"]==''&&formValues["level"]==''&&formValues["isIncome"]==''&&formValues["isIncome"]!=0) {
store.getProxy().extraParams ={ };
store.reload();
}else if(formValues["createTime"]==''){
store.getProxy().extraParams ={ };
//alert('createTime kong');
//1.清空所有查询条件
Ext.apply(store.proxy.extraParams, {
orderNumber:'',
//createTime:'',
level:'',
isIncome:''
});
Ext.apply(store.proxy.extraParams, {
orderNumber:this.lookupReference('orderSearchForm-orderNumber').getValue(),
level:this.lookupReference('orderSearchForm-level').getValue(),
isIncome:this.lookupReference('orderSearchForm-isIncome').getValue()
//createTime:null,
});
store.load({params: {start:0,limit:14,page:1}});
}else{
//1.清空所有查询条件
Ext.apply(store.proxy.extraParams, {
orderNumber:'',
createTime:'',
level:'',
isIncome:''
});
Ext.apply(store.proxy.extraParams, {
orderNumber:this.lookupReference('orderSearchForm-orderNumber').getValue(),
level:this.lookupReference('orderSearchForm-level').getValue(),
createTime:Ext.util.Format.date(this.lookupReference('orderSearchForm-createTime').getValue(), 'Y/m/d H:i:s'),
isIncome:this.lookupReference('orderSearchForm-isIncome').getValue()
});
store.load({params: {start:0,limit:14,page:1}});
}
//alert(store.proxy.extraParams.createTime);
//myOrderGridQueryForm.form.reset();
//btn.up('gridpanel').reset();
}
,
orderGridExportXls:function(){
//alert("导出功能");
/* Ext.Ajax.request( {
url : 'order/excel/export',
method : 'get',
success : function(response, options) {
var json = Ext.util.JSON.decode(response.responseText);
if(json.success){
Ext.Msg.alert('操作成功', json.msg);
grid.getStore().reload();
}else{
Ext.Msg.alert('操作失败', json.msg);
}
},
failure : function() {
alert("failse");
}
});*/
window.location.href = "order/excel/export";
}
});
eight:添加数据需要弹出一个外框组件 — — OrderGridWindow.js
Ext.define('Admin.view.order.OrderGridWindow', {
extend: 'Ext.window.Window',
alias: 'widget.orderGridWindow',
autoShow: true,
modal: true,
layout: 'fit',
// width: 200,
//height: 200,
afterRender: function () {
var me = this;
me.callParent(arguments);
me.syncSize();
// Since we want to always be a %age of the viewport, we have to watch for
// resize events.
Ext.on(me.resizeListeners = {
resize: me.onViewportResize,
scope: me,
buffer: 50
});
},
doDestroy: function () {
Ext.un(this.resizeListeners);
this.callParent();
},
onViewportResize: function () {
this.syncSize();
},
syncSize: function () {
var width = Ext.Element.getViewportWidth(),
height = Ext.Element.getViewportHeight();
// We use percentage sizes so we'll never overflow the screen (potentially
// clipping buttons and locking the user in to the dialog).
this.setSize(Math.floor(width * 0.36), Math.floor(height * 0.52));
this.setXY([ Math.floor(width * 0.05), Math.floor(height * 0.05) ]);
}
});
nine :弹窗组件中放入一个 表单 — — OrderGridForm.js
Ext.define('Admin.view.order.OrderGridForm', {
extend: 'Ext.form.Panel',
alias: 'widget.orderGridForm',
requires: [
'Ext.button.Button',
'Ext.form.field.Text',
'Ext.form.field.File',
'Ext.form.field.HtmlEditor',
'Ext.form.field.TextArea',
'Ext.form.field.Time',
'Ext.form.field.ComboBox',
'Ext.form.field.Date',
'Ext.form.field.Radio',
'Ext.form.field.Hidden'
],
//viewModel: {type: 'emailcompose'},
//cls: 'email-compose',
controller: 'orderViewController',
layout: {
type:'vbox',
align:'stretch'
},
bodyPadding: 10,
scrollable: true,
defaults: {
labelWidth: 75,
labelSeparator: ':'
},
items: [{
xtype: 'hidden',
fieldLabel: 'Id',
name:'orderId'
},
{
xtype: 'hidden',
fieldLabel: 'isIncome',
name:'isIncome'
},{
xtype: 'textfield',
fieldLabel: '订单编号',
blankText:'订单编号不能为空',
allowBlank: false,
name:'orderNumber'
},{
xtype: 'datefield',
format: 'Y/m/d H:i:s',
fieldLabel: '创建时间',
blankText:'创建时间不能为空',
editable:true,
allowBlank: false,
name:'createTime'
},{
xtype: 'combobox',
fieldLabel: '订单优先级',
blankText:'优先级不能为空',
editable:false,
allowBlank: false,
name:'level',
store: Ext.create('Ext.data.Store', {
fields: ['value', 'name'],
data : [
{"value":"HIGH", "name":"高"},
{"value":"MEDIUM", "name":"中"},
{"value":"LOW", "name":"低"}
]
}),
queryMode: 'local',
displayField: 'name',
valueField: 'value'
},
{
xtype: 'combobox',
fieldLabel: '选择供应商',
blankText:'供应商不能为空',
allowBlank: false,
name:'supplierId',
store: {
type:'orderShowSupplierStore'
},
queryMode: 'local',
displayField: 'suppName',
valueField: 'id',
listeners:{
expand: function(combo, record, index) {
combo.store.reload();
}
}
}
,
{
xtype: 'combobox',
fieldLabel: '选择商品',
blankText:'商品名称不能为空',
allowBlank: false,
name:'pid',
store: {
type:'orderShowProductStore'
},
queryMode: 'local',
displayField: 'pname',
valueField: 'pid',
listeners:{
expand: function(combo, record, index) {
combo.store.reload();
}
}
}
/*,{
xtype: 'combobox',
fieldLabel: '选择商品',
editable:false,
allowBlank: false,
name:'pid',
store: Ext.create('Ext.data.Store', {
fields: ['value', 'name'],
data : [
{"value":"11", "name":"小郑"},
{"value":"12", "name":"林霞"},
{"value":"13", "name":"zz"},
{"value":"14", "name":"欣欣"},
{"value":"15", "name":"小杰"},
]
}),
queryMode: 'local',
displayField: 'name',
valueField: 'value'
}
*/
,{
xtype: 'textfield',
fieldLabel: '产品数量',
regex:/^[0-9]*[1-9][0-9]*$/,
regexText:'请输入正整数',
blankText:'数量不能为空',
allowBlank: false,
name:'pnumber'
}],
bbar: {
items: ['->',{
xtype: 'button',
//ui: 'soft-red',
text: '保存',
handler: 'orderGridFormSubmit'
},{
xtype: 'button',
//ui: 'gray',
text: '取消',
handler: 'orderGridWindowClose'
}]
}
});
综上所述:九个步骤即可开发出这个模块