extjs mvc 架構
有別於其他的MVC架構,EXTJS 有自己的定義
Model : 一個field 以及 他的data的集合。 Modles 知道如何持久化自己一般使用Stores 來表示數據以用於grids等component
View: 一種component的類型,grids,trees 以及panels等
Controller用來放使得app工作的代碼,例如 render views , instantiating Models 或者其他應用邏輯
Extjs 所有的MVC 程序都是用Application 類的實例開始的 。裏面包含了這個應用的全局變量,如應用名,同時還包含了應用所需要的models,views以及controllers。 此外還包含了一個launch函數,這個函數會在加載的時候自動運行。例如
Ext.application({
name: 'AM',
appFolder: 'app',
controllers: [
'Users'
],
launch: function() {
Ext.create('Ext.container.Viewport', {
layout: 'fit',
items: [
{
xtype: 'panel',
title: 'Users',
html : 'List of users will go here'
}
]
});
}
});
這裏我們定義了一個應用名,系統會自動增加這樣一個namespace ,此外,定義了相對的路徑app.還告訴系統我們要用到Users這個controller.最終我們用launch定義了一個viewprot.
一般來說,一個系統會有多個controller ,一般是一個Model對用一個controller.
定義個controller:
controller是一箇中介,主要是監聽事件,特別是來自view的時間,以決定我們的系統如何繼續運行。
Ext.define('AM.controller.Users', {
extend: 'Ext.app.Controller',
init: function() {
console.log('Initialized Users! This happens before the Application launch function is called');
}
});
注意,contorller 是在上述的application 實例中定義和調用。這裏的init函數會在launch 之前調用 。然後,我們完善init 函數 。在init 函數裏面這樣寫
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');
}
});
這裏使用了一個ComponentQuery 來,獲得compontent ,簡單的說這個這裏使用了一個ComponentQuery就是使用一種類似CSS代碼的方法選擇component。這裏的意思是選擇所有是viewport的孩子panel的component.都調用onPanelRendered這個函數
下面我們定義view 首先定義個List 用來展示數據
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: '[email protected]'},
{name: 'Tommy', email: '[email protected]'}
]
};
this.columns = [
{header: 'Name', dataIndex: 'name', flex: 1},
{header: 'Email', dataIndex: 'email', flex: 1}
];
this.callParent(arguments);
}
});
這個view是一個最普通的component 。 一個grid panel的擴展 。這裏的 alias 的作用就是讓我們可以使用xtype 函數來創建Item。
然後就是使用這個list
首先實現修改user.js 裏的controller 文件,來增加view的支持
Ext.define('AM.controller.Users', {
extend: 'Ext.app.Controller',
views: [
'user.List'
],
init: ...
onPanelRendered: ...
});
And then render it inside the main viewport by changing app.js to:
Ext.application({
name: 'AM',
controllers: [
'Users'
],
launch: function() {
Ext.create('Ext.container.Viewport', {
layout: 'fit',
items: {
xtype: 'userlist'
}
});
}
});
注意,我們是需要在controller裏面添加view這個數組,這樣,當app 初始化 controllers數組以後,就會同時初始化這個controller裏面的views 。這樣,我們就能在viewport的item裏面xtype了userlist。
這時候onrendered 函數同樣會被調用,因爲list實際上是一個gridpanel 。所以我們將controller修改如下
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'));
}
});
注意,這裏直接使用了 userlist 以簡化,而對應的事件則是itedblclick 。也就是雙擊一行。
然後我們新建一個 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);
}
});
這個是一個簡單的包含form的window 。以用來顯示彈出的數據,包含兩行 name 和 email
同樣,我們擴展controller
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);
}
});
將eidt 增加到views數組裏面,並增加一個editUser函數。注意這裏使用了一個down 函數,這也是一個componentQuery函數。在Extjs4 裏面,所有的component都有一個down方法,以用來快速找尋其孩子component
爲了使用store 我們需要改兩個地方,
Ext.define('AM.controller.Users', {
extend: 'Ext.app.Controller',
stores: [
'Users'
],
...
});
then we'll update app/view/user/List.js to simply reference the Store by id:
Ext.define('AM.view.user.List' ,{
extend: 'Ext.grid.Panel',
alias : 'widget.userlist',
//we no longer define the Users store inline
store: 'Users',
...
});
在這裏將stores 放到 controller的 stores 數組裏面,這樣系統會自動裝在這個store並且建立storeid,這樣我們可以很容易的在view裏面使用這個store 如 store: 'Users'。
在Extjs 裏面提供給了一個強大的Model 類,用它我們可以很方便的編輯我們的內容。
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: 'User',
data: [
{name: 'Ed', email: '[email protected]'},
{name: 'Tommy', email: '[email protected]'}
]
});
注意,是在sore裏面添加 model的reference 。
下面我們在controller 裏面監聽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');
}
});
這也是一個 ComponentQuery selector 。首先找到useredit,然後找到button有save 這個action的button 這個action:save 的參數是我們在xtype useredit 的時候傳進去的,而它給了我們一個快速找到這個button的方法 。
測試能夠正確找到這個button以後,我們就可以完善方法了
updateUser: function(button) {
var win = button.up('window'),
form = win.down('form'),
record = form.getRecord(),
values = form.getValues();
record.set(values);
win.close();
}
這裏我們使用up 來找到我們的父component,這樣點擊save 就可以將數據保存到 record 裏面了。 下一步就是保存到server上
首先先將讀取設成ajax 模式
Ext.define('AM.store.Users', {
extend: 'Ext.data.Store',
model: 'User',
autoLoad: true,
proxy: {
type: 'ajax',
url: 'data/users.json',
reader: {
type: 'json',
root: 'users',
successProperty: 'success'
}
}
});
這裏,我們將date 換成了proxy ,這種格式可以讓store 或者 model 保存或者讀取數據。爲了保存數據,我們需要修改一個這個sotre 的proxy
proxy: {
type: 'ajax',
api: {
read: 'data/users.json',
update: 'data/updateUsers.json'
},
reader: {
type: 'json',
root: 'users',
successProperty: 'success'
}
}
然後,在編輯完成以後讓其同步一下來將數據上傳
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();
}