有许多MVC体系结构,其中大多数都是彼此略有不同。这是EXT JS4中的。
模型:字段和数据的集合。模型知道如何通过数据包存储,能通过协议连接到其他模型。
视图:任何类型的组件——网格、树和面板是所有视图。
控制器:存放所有使应用程序工作的代码的地方——不管是渲染的视图,实例化模型,或任何其他应用程序逻辑。
模型:字段和数据的集合。模型知道如何通过数据包存储,能通过协议连接到其他模型。
视图:任何类型的组件——网格、树和面板是所有视图。
控制器:存放所有使应用程序工作的代码的地方——不管是渲染的视图,实例化模型,或任何其他应用程序逻辑。
一、文件结构
EXT JS4中应用遵循统一的目录结构,所以每一个应用程序都是相同的。在MVC布局中,所有的类都放在了app文件夹,该文件夹依次包含了存放模型、视图、控制器和存储的文件夹。
二、实战代码
1.index.html
<html>
<head>
<title>Account Manager</title>
<link rel="stylesheet" type="text/css" href="ext-4.0/resources/css/ext-all.css">
<script type="text/javascript" src="ext-4.0/ext-debug.js"></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body></body>
</html>
2.app.js
Ext.application({
requires: 'Ext.container.Viewport',
name: 'AM',
appFolder: 'app',
launch: function() {
Ext.create('Ext.container.Viewport', {
layout: 'fit',
items: [
{
xtype: 'panel',
title: 'Users',
html : 'List of users will go here'
}
]
});
}
});
3.定义控制器
Users.js:
Ext.define('AM.controller.Users', {
extend: 'Ext.app.Controller',
init: function() {
console.log('Initialized Users! This happens before the Application launch function is called');
}
});
添加新建的Users 控制器到app.js中的应用配置中:
Ext.application({
...
controllers: [
'Users'
],
...
});
当用应该程序在浏览器上访问 index.html
时,Users
控制器会自控装载(因为我们指定它在应用定义以上),init 函数在应用程序的launch函数启动之前被调用。
init
函数是一个很棒的地方来来简历控制器如何与视图交互 ,通常是与另一个控制器函数——control结合使用。control函数使得它容易监听视图类中的事件,并对处理函数采取一些措施。更新ourUsers控制器,设定什么时候渲染面板,Users.js:
Ext.define('AM.controller.Users', {
extend: 'Ext.app.Controller',
init: function() {
this.control({
'viewport > panel': {
render: this.onPanelRendered
}
});
},
onPanelRendered: function() {
console.log('The panel was rendered');
}
});
control函数使用ComponentQuery引擎,以快速方便地得到页面上的参考部件。
'viewport > panel'
可翻译成"find every Panel that is a direct child of a Viewport"。然后,我们提供了一个对象映射事件名(例子中只有渲染)处理功能。整体效果是无论何时任何组件匹配到选择器(即
'viewport > panel'
)时,触发render事件,onPanelRendered函数被调用。
4.定义视图
视图通常定义成Ext .JS .component的子类,List.js
:
Ext.define('AM.view.user.List' ,{
extend: 'Ext.grid.Panel',
alias : 'widget.userlist',
title : 'All Users',
initComponent: function() {
this.store = {
fields: ['name', 'email'],
data : [
{name: 'Ed', email: 'ed@sencha.com'},
{name: 'Tommy', email: 'tommy@sencha.com'}
]
};
this.columns = [
{header: 'Name', dataIndex: 'name', flex: 1},
{header: 'Email', dataIndex: 'email', flex: 1}
];
this.callParent(arguments);
}
});
我们有可能继承Grid Component,建立一个别名(alias),以便可以用它作为一个xtype。
然后添加这个视图到Users控制器中,由于我们用
修改User.js:
然后添加这个视图到Users控制器中,由于我们用
'widget.'
格式设置了一个别名,我们可以用'userlist'作为一个xtype,就像先前用的
'panel'
一样。Users.js:
Ext.define('AM.controller.Users', {
extend: 'Ext.app.Controller',
views: [
'user.List'
],
init: ...
onPanelRendered: ...
});
通过修改app.js中的launch函数
,把它渲染到主视图中:
Ext.application({
...
launch: function() {
Ext.create('Ext.container.Viewport', {
layout: 'fit',
items: {
xtype: 'userlist'
}
});
}
});
'user.List'
告诉应用程序自动加载文件。
5.控制网格
Ext.define('AM.controller.Users', {
extend: 'Ext.app.Controller',
views: [
'user.List'
],
init: function() {
this.control({
'userlist': {
itemdblclick: this.editUser
}
});
},
editUser: function(grid, record) {
console.log('Double clicked on ' + record.get('name'));
}
});
我们改变了 ComponentQuery 选择器(
'userlist'
),事件名称 (
'itemdblclick'
),处理函数名称 (
'editUser'
)。
Edit.js
:
Ext.define('AM.view.user.Edit', {
extend: 'Ext.window.Window',
alias : 'widget.useredit',
title : 'Edit User',
layout: 'fit',
autoShow: true,
initComponent: function() {
this.items = [
{
xtype: 'form',
items: [
{
xtype: 'textfield',
name : 'name',
fieldLabel: 'Name'
},
{
xtype: 'textfield',
name : 'email',
fieldLabel: 'Email'
}
]
}
];
this.buttons = [
{
text: 'Save',
action: 'save'
},
{
text: 'Cancel',
scope: this,
handler: this.close
}
];
this.callParent(arguments);
}
});
我们再一次使用initComponent来指定复杂对象items和buttons。
添加视图到控制器,渲染并加载它。Users.js:
Ext.define('AM.controller.Users', {
extend: 'Ext.app.Controller',
views: [
'user.List',
'user.Edit'
],
init: ...
editUser: function(grid, record) {
var view = Ext.widget('useredit');
view.down('form').loadRecord(record);
}
});
我们用方法
Ext.widget
创建了一个视图,相当于
Ext.create('widget.useredit')
。然后我们用ComponentQuery再次快速获取一个编辑窗口的表单,在Ext JS 4中,每个组件都有一个down函数,该函数接受ComponentQuery选择器来找子组件。
6.创建一个模型和一个存储
:app/store/
Users.js
Ext.define('AM.store.Users', {
extend: 'Ext.data.Store',
fields: ['name', 'email'],
data: [
{name: 'Ed', email: 'ed@sencha.com'},
{name: 'Tommy', email: 'tommy@sencha.com'}
]
});
让Users控制器加载时包括这个store,修改app/
controller/U
sers.js:
Ext.define('AM.controller.Users', {
extend: 'Ext.app.Controller',
stores: [
'Users'
],
...
});
修改
app/view/user/List.js
:
Ext.define('AM.view.user.List' ,{
extend: 'Ext.grid.Panel',
alias : 'widget.userlist',
//we no longer define the Users store in the `initComponent` method
store: 'Users',
...
});
app/model/User.js
:
Ext.define('AM.model.User', {
extend: 'Ext.data.Model',
fields: ['name', 'email']
});
修改控制器和存储:
//the Users controller will make sure that the User model is included on the page and available to our app
Ext.define('AM.controller.Users', {
extend: 'Ext.app.Controller',
stores: ['Users'],
models: ['User'],
...
});
// we now reference the Model instead of defining fields inline
Ext.define('AM.store.Users', {
extend: 'Ext.data.Store',
model: 'AM.model.User',
data: [
{name: 'Ed', email: 'ed@sencha.com'},
{name: 'Tommy', email: 'tommy@sencha.com'}
]
});
7.用模型保存数据
更新控制器,使它能监听save按钮:
Ext.define('AM.controller.Users', {
init: function() {
this.control({
'viewport > userlist': {
itemdblclick: this.editUser
},
'useredit button[action=save]': {
click: this.updateUser
}
});
},
updateUser: function(button) {
console.log('clicked the Save button');
}
});
'useredit button[action=save]'
:用
'useredit'
xtype来 聚焦道正在编辑的用户窗口,然后在窗口中寻找拥有
'save'
action的任何按钮。
编辑save按钮事件:
updateUser: function(button) {
var win = button.up('window'),
form = win.down('form'),
record = form.getRecord(),
values = form.getValues();
record.set(values);
win.close();
}
button.up('window')
找到正在编辑的用户窗口,
win.down('form')
找到表单
8.保存到服务器
使用ajax:
Ext.define('AM.store.Users', {
extend: 'Ext.data.Store',
model: 'AM.model.User',
autoLoad: true,
proxy: {
type: 'ajax',
url: 'data/users.json',
reader: {
type: 'json',
root: 'users',
successProperty: 'success'
}
}
});
我们移除了
'data'
属性,用‘porxy’来代替。在EXT JS4中proxy是一种从一个store或模型中加载和保存数据的方法,有AJAX, JSON-P 和HTML5 porxy。例子中加载的数据来自于
'data/users.json'
。
创建data/users.json
{
success: true,
users: [
{id: 1, name: 'Ed', email: 'ed@sencha.com'},
{id: 2, name: 'Tommy', email: 'tommy@sencha.com'}
]
}
对proxy做一点小变化
proxy: {
type: 'ajax',
api: {
read: 'data/users.json',
update: 'data/updateUsers.json'
},
reader: {
type: 'json',
root: 'users',
successProperty: 'success'
}
}
仍旧从users.json中读数据,但任何修改都会发送到
updateUsers.json
中。
updateUsers.json文件中仅仅包含
{"success": true}
.
updateUser: function(button) {
var win = button.up('window'),
form = win.down('form'),
record = form.getRecord(),
values = form.getValues();
record.set(values);
win.close();
this.getUsersStore().sync();
}
告诉store编辑之后,同步它自己。