久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

ExtJs 4 中的MVC應(yīng)用架構(gòu)

 sunvins 2017-12-24

一,、ExtJs 4.x MVC模式的原理與作用

大規(guī)??蛻舳藨?yīng)用通常不好實(shí)現(xiàn)不好組織也不好維護(hù),因?yàn)楣δ芎腿肆Φ牟粩嘣黾?,這些應(yīng)用的規(guī)模很快就會(huì)超出掌控能力,,ExtJS4帶來(lái)了一個(gè)新的應(yīng)用架構(gòu),不但可以組織代碼,,還可以減少實(shí)現(xiàn)的內(nèi)容,。

新的應(yīng)用架構(gòu)遵照一個(gè)類MVC的模式,模型(Models)和控制器(Controllers)首次被引入,。業(yè)界有很多種MVC架構(gòu),,基本大同小異,ExtJS4的定義如下:

a.Model模型:模型是字段和它們的數(shù)據(jù)的集合,,例如User模型帶有username和password字段,,模型知道如何持久化自己的數(shù)據(jù),并且可以和其他模型關(guān)聯(lián),模型跟ExtJS 3 中的Record類有點(diǎn)像(區(qū)別是,,Record只是單純的扁平結(jié)構(gòu),,而Model可以nest),通常都用在Store中去展示grid和其他組件的數(shù)據(jù),。

b.View視圖:視圖是組件的一種,,專注于界面展示 – grid, tree, panel 都是view。

c.Controllers控制器:一個(gè)安放所有使你的app正確工作的代碼的位置,,具體一點(diǎn)應(yīng)該是所有動(dòng)作,,例如如何渲染view,如何初始化model,,和app的其他邏輯,。

請(qǐng)注意:MVC是一個(gè)框架,不是設(shè)計(jì)模式,,更多的內(nèi)容請(qǐng)參考: 百度百科

框架與設(shè)計(jì)模式雖然相似,,但卻有著根本的不同。設(shè)計(jì)模式是對(duì)在某種環(huán)境中反復(fù)出現(xiàn)的問(wèn)題以及解決該問(wèn)題的方案的描述,,它比框架更抽象,;框架可以用代碼表示,也能直接執(zhí)行或復(fù)用,,而對(duì)模式而言只有實(shí)例才能用代碼表示;設(shè)計(jì)模式是比框架更小的元素,,一個(gè)框架中往往含有一個(gè)或多個(gè)設(shè)計(jì)模式,框架總是針對(duì)某一特定應(yīng)用領(lǐng)域,,但同一模式卻可適用于各種應(yīng)用,。可以說(shuō),,框架是軟件,,而設(shè)計(jì)模式是軟件的知識(shí)。

簡(jiǎn)而言之:設(shè)計(jì)模式是大智慧,,用來(lái)對(duì)軟件設(shè)計(jì)進(jìn)行分工,;框架模式是小技巧,對(duì)具體問(wèn)題提出解決方案,,以提高代碼復(fù)用率,,降低耦合度。

二,、ExtJs 4 MVC框架搭建

2.1,、文件結(jié)構(gòu)

ExtJS 4 應(yīng)用都遵循一個(gè)統(tǒng)一的目錄結(jié)構(gòu),每個(gè)應(yīng)有都相同 MVC中,,所有類都放在app目錄里面,,這個(gè)目錄可以有子目錄,,代表的是命名空間(一個(gè)子目錄對(duì)應(yīng)一個(gè)命名空間),使用不同的目錄存放views,models,controllers,stores,。當(dāng)我們完成例子的時(shí)候,,目錄結(jié)構(gòu)應(yīng)該和下圖一樣:

ExtJS SDK必須的文件在目錄ext4中,因此,,index.html應(yīng)該引入extjs必須的js和css,,以及app.js文件

2.2、在app.js中創(chuàng)建應(yīng)用

每個(gè)ExtJS 4的應(yīng)用都從一個(gè)Application類的實(shí)例開(kāi)始,,這個(gè)實(shí)例包含應(yīng)用的全局配置(例如應(yīng)用的名字),,這個(gè)實(shí)例也負(fù)責(zé)維護(hù)對(duì)全部模型、視圖,、控制器的引用的維護(hù),,還有一個(gè)launch函數(shù),會(huì)在所有加載項(xiàng)加載完成之后調(diào)用,。

首先需要選擇一個(gè)全局命名空間,,所有ExtJS4應(yīng)用都需要有一個(gè)全局命名空間,以讓所有應(yīng)用中的類安放到其中:

復(fù)制代碼
Ext.application({ requires: ['Ext.container.Viewport'], name: 'FWY',//定義的命名空間 appFolder: 'app',//指明應(yīng)用的根目錄 launch: function() { Ext.create('Ext.container.Viewport', { layout: 'fit', items: [ { xtype: 'panel', title: '標(biāo)題', html : '內(nèi)容' } ] }); } });
復(fù)制代碼

2.3,、定義一個(gè)控制器

控制器是應(yīng)用的粘合劑,,它們所作的事情就是監(jiān)聽(tīng)事件并執(zhí)行動(dòng)作,繼續(xù)我們的應(yīng)用,,創(chuàng)建一個(gè)控制器。創(chuàng)建app/controller/Students.js這個(gè)文件,,并添加如下代碼:

復(fù)制代碼
Ext.define('FWY.controller.Students', { extend: 'Ext.app.Controller', init: function() { console.debug('trigger controller init event'); } });
復(fù)制代碼

接下來(lái)在app.js中添加對(duì)Students控制器的引用:

復(fù)制代碼
Ext.application({ ... controllers: [ 'Students' //對(duì)應(yīng)于controller文件夾下面的Students.js ], ... });
復(fù)制代碼

當(dāng)我們通過(guò)index.html查看應(yīng)用,,Students控制器會(huì)被自動(dòng)加載(因?yàn)樵赼pp.js的Application中增加了引用),并且Students的init方法會(huì)在launch之前調(diào)用,。

init方法是個(gè)極好的地方,,可以用來(lái)設(shè)置如何和view交互,通常都使用Controller的一個(gè)方法control,,control方法使得監(jiān)聽(tīng)view的事件變的容易,,更新一下控制器,讓它告知我們panel何時(shí)渲染:

復(fù)制代碼
Ext.define('FWY.controller.Students', { extend: 'Ext.app.Controller', init: function() { this.control({ 'viewport > panel': { render: this.onPanelRendered } }); }, onPanelRendered: function() { console.debug('該panel被渲染了'); } });
復(fù)制代碼

我們已經(jīng)更新了init方法,,使用this.controll給視圖設(shè)置監(jiān)聽(tīng)器,。這個(gè)controll方法,使用最新的組件查詢引擎(ComponentQuery)可以快速方便的找到頁(yè)面上的組件,。如果你對(duì)ComponentQuery不熟悉,,可以查看ComponentQuery文檔進(jìn)行詳細(xì)了解。簡(jiǎn)要一點(diǎn),,ComponentQuery可以允許我們使用一個(gè)類似css選擇器的方式找到組件,。

在例子的init方法中我們應(yīng)用了'viewport > panel',,可以解釋為“查找Viewport直接后代中的所有Panel組件”,然后我們提供了一個(gè)對(duì)象匹配事件名稱(這個(gè)例子中只用了render)來(lái)提供響應(yīng)函數(shù),。全部的影響就是無(wú)論哪個(gè)組件符合我們的選擇器,,當(dāng)它的render事件觸發(fā)時(shí),我們的onPanelRendered函數(shù)都會(huì)被調(diào)用,。

三,、創(chuàng)建ExtJs4 MVC應(yīng)用

1、定義一個(gè)視圖

直到現(xiàn)在,,我們的應(yīng)用只有很少代碼,,只有兩個(gè)文 件 app.js 和 app/controller/Students.js,現(xiàn)在我們想增加一個(gè)grid顯示所有系統(tǒng)中的學(xué)生列表,,修改3處:

(1),、添加view/List.js視圖

是時(shí)候更好的組織一下邏輯并開(kāi)始使用視圖了。

視圖也是組件,,通常都是ExtJS現(xiàn)有組件的子類,,現(xiàn)在準(zhǔn)備創(chuàng)建學(xué)生表,先創(chuàng)建 app/view/student/List.js ,,添加代碼:

復(fù)制代碼
Ext.define('FWY.view.student.List' ,{ extend: 'Ext.grid.Panel', alias : 'widget.studentlist', title : '學(xué)生信息列表', initComponent: function() { this.store = { fields: ['id','name', 'age','sex'], data : [ {id:1,name: 'zhangsan', age: 18,sex:'boy'}, {id:2,name: 'lishi', age: 20,sex:'girl'} ]}; this.columns = [ {header: '編號(hào)', dataIndex: 'id', flex: 1}, {header: '姓名', dataIndex: 'name', flex: 1}, {header: '年齡', dataIndex: 'age', flex: 1}, {header: '性別', dataIndex: 'sex', flex: 1} ]; this.callParent(arguments); } });
復(fù)制代碼
(2),、修改controller/Students.js

我們的視圖類就是一個(gè)普通的類,這個(gè)例子中我們擴(kuò)展了 Grid 組件,,并設(shè)置了別名,,這樣我們可以用 xtype 的方式調(diào)用這個(gè)組件,另外我們也添加了 store 和 columns 的配置,。 接下來(lái)我們需要添加這個(gè)視圖到 Students控制器,。因?yàn)槲覀冇?'widget.studentlist' 設(shè)置了別名,所以我們可以使用 studentlist 作為xtype,,就像我們使用之前使用的 'panel'

復(fù)制代碼
Ext.define('FWY.controller.Students', { extend: 'Ext.app.Controller', views: [ 'student.List'//添加view視圖 ], init: ... onPanelRendered: ... });
復(fù)制代碼
(3),、修改app.js,加載視圖

接下來(lái)修改 app.js 讓視圖在viewport中渲染,,需要修改 launch 方法

復(fù)制代碼
Ext.application({ ... launch: function() { Ext.create('Ext.container.Viewport', { layout: 'fit', items: { xtype: 'studentlist' } }); } });
復(fù)制代碼

唯一需要注意的是我們?cè)趘iews數(shù)組中指定了 'student.List' ,,這告訴應(yīng)用去自動(dòng)加載對(duì)應(yīng)的文件,ExtJS4 的動(dòng)態(tài)加載系統(tǒng)會(huì)根據(jù)規(guī)則從服務(wù)器自動(dòng)拉取文件,,例如student.List就是規(guī)則,,把.替換成/就是文件存放路徑。刷新一下頁(yè)面即可看到效果

2,、添加對(duì)列表的控制

分三步完成對(duì)對(duì)編輯窗體的控制

(1),、為grid綁定雙擊事件

注意 onPanelRendered 方法依然被調(diào)用,因?yàn)槲覀兊膅rid依然滿足 'viewport > panel' 選擇器,,因?yàn)槲覀兊囊晥D繼承自 Grid ,,從而繼承自 Panel?,F(xiàn)在我們需要收緊一下選擇器,我們使用xtype作為選擇器替換之前的 'viewport > panel' ,,監(jiān)聽(tīng)雙擊事件,,以便繼續(xù)做編輯用戶信息:

復(fù)制代碼
Ext.define('FWY.controller.Students', { extend: 'Ext.app.Controller', views: [ 'student.List' ], init: function() { this.control({ 'studentlist': { itemdblclick: this. editStudent//添加行雙擊事件 } }); }, editStudent: function(grid, record) { console.log('Double clicked on ' record.get('name')); } });
復(fù)制代碼

注意我們更換了組件查詢選擇器為 'studentlist' ,監(jiān)聽(tīng)的事件更改為 'itemdblclick' ,,響應(yīng)函數(shù)設(shè)置為 editStudent,,現(xiàn)在只是簡(jiǎn)單的日志出雙擊行的name屬性。

(2),、創(chuàng)建view/student/Edit.js視圖

可以看到日志是正確的,,但我們實(shí)際想做的是編輯用戶信息,讓我們現(xiàn)在做,,創(chuàng)建一個(gè)新的視圖 app/view/student/Edit.js

復(fù)制代碼
Ext.define('FWY.view.student.Edit', { extend: 'Ext.window.Window', alias : 'widget.studentedit', title : '修改學(xué)生信息', layout: 'fit', autoShow: true, initComponent: function() { this.items = [ { xtype: 'form', items: [ { xtype: 'textfield', name : 'name', fieldLabel: '姓名' }, { xtype: 'textfield', name : 'age', fieldLabel: '年齡' }, { xtype: 'textfield', name : 'sex', fieldLabel: '性別' } ] } ]; this.buttons = [ { text: '保存', action: 'save' }, { text: '取消', scope: this, handler: this.close } ]; this.callParent(arguments); } });
復(fù)制代碼
(3),、修改控制器加載視圖

接下來(lái)我們要做的就是在控制器加載這個(gè)視圖,渲染并且加載用戶信息:

復(fù)制代碼
Ext.define('FWY.controller.Students', { extend: 'Ext.app.Controller', views: [ 'student.List', 'student.Edit'//添加edit視圖 ], init: ... editStudent: function(grid, record) { var view = Ext.widget('studentedit');//注冊(cè)組件,,顯示窗口 view.down('form').loadRecord(record);//加載數(shù)據(jù)到表單中 } });
復(fù)制代碼

首先我們用 Ext.widget 方法創(chuàng)建了視圖,,這個(gè)方法等同于 Ext.create('widget.studentedit') ,然后我們又一次借助組件查詢找到了窗口中的表單,,每個(gè)ExtJS4中的組件都有一個(gè) down方法,,可以借助組件查詢支持的選擇器來(lái)迅速找到任意下層的組件,雙擊表格中的一行可以看到彈窗效果。

3,、創(chuàng)建Store和Model進(jìn)行重構(gòu)

現(xiàn)在我們有了表單,,可以開(kāi)始編輯和保存用戶信息了,但是這之前需要做一點(diǎn)點(diǎn)重構(gòu),。 FWY.view.student.List 創(chuàng)建了一個(gè)內(nèi)聯(lián)的 Store ,,這樣可以工作但是我們需要把 Store 分離出來(lái)以便我們?cè)趹?yīng)用的其他位置可以引用并更新其中的信息,我們把它放在它應(yīng)該在的文件中 app/store/Students.js

復(fù)制代碼
Ext.define('FWY.store.Students', { extend: 'Ext.data.Store', fields: ['id','name', 'age','sex'], data: [ {id:1,name: '張三', age: 30,sex:'男'}, {id:2,name: '李四', age: 20,sex:'女'} ] });
復(fù)制代碼

現(xiàn)在我們需要做兩處變更,,首先我們需要讓 Students 初始化的時(shí)候加載這個(gè) Store :

Ext.define('FWY.controller.Students', { extend: 'Ext.app.Controller', stores: ['Students'],//加載store ... });

然后我們要把之前直接在視圖中內(nèi)聯(lián)的store更改掉,,

復(fù)制代碼
Ext.define('FWY.view.student.List' ,{ extend: 'Ext.grid.Panel', alias : 'widget.studentlist', store: 'Students',//引用Store ... });
復(fù)制代碼

控制器的代碼中中引入了store,,store會(huì)被自動(dòng)加載到頁(yè)面并賦予一個(gè)storeId,,這讓視圖中使用store變的容易(這個(gè)例子中,只要配置 store: 'Students' 就可以了) 現(xiàn)在我們只是在store中內(nèi)聯(lián)的定義了四個(gè)字段 (id,name,age,sex),,這樣可以工作了,。

進(jìn)一步重構(gòu):

ExtJS4中有一個(gè)強(qiáng)大的 Ext.data.Model類,在編輯用戶的時(shí)候我們可以借助它,,使用Model重構(gòu)下Store,,在 app/model/Student.js中創(chuàng)建一個(gè)Model:

Ext.define('FWY.model.Student', { extend: 'Ext.data.Model', fields: ['id','name','age','sex'] });

這就是定義我們的Model需要做的,現(xiàn)在需要讓Store引用Model替換掉使用內(nèi)聯(lián)字段的方式,,并且讓控制器也引用Model:

復(fù)制代碼
//修改控制器,,引用Model Ext.define('FWY.controller.Students', { extend: 'Ext.app.Controller', stores: ['Students'], models: ['Student'], ... }); //修改store,,引用Model Ext.define('FWY.store.Students', { extend: 'Ext.data.Store', model: 'FWY.model.Student', data: [ {id:1,name: '張三1', age: 30,sex:'男'}, {id:2,name: '李四1', age: 21,sex:'女'} ] });
復(fù)制代碼

4、利用模型保存數(shù)據(jù)

現(xiàn)在我們有了一個(gè)用戶數(shù)據(jù)表,,雙擊每?一行都能打開(kāi)一個(gè)編輯窗口,,現(xiàn)在要做的是保存編輯變更,編輯窗口有一個(gè)編輯表單,,還有保存按鈕,,現(xiàn)在我們更新一下控制器讓保存按鈕有響應(yīng):

復(fù)制代碼
Ext.define('FWY.controller.Students', { init: function() { this.control({ 'viewport > studentlist': { itemdblclick: this.editStudent }, 'studentedit button[action=save]': {//獲取studentedit視圖中的button配置action=‘save’的按鈕事件 click: this.updateStudent } }); }, updateStudent: function(button) { console.log('clicked the Save button'); } });
復(fù)制代碼

接下來(lái)填充 updateStudent 真正的邏輯。我們需要把數(shù)據(jù)從表單中取出,,再 設(shè)置回store中:

復(fù)制代碼
updateStudent: function(button) { var win = button.up('window'), form = win.down('form'), record = form.getRecord(), values = form.getValues(); record.set(values); win.close(); }
復(fù)制代碼

5,、保存到服務(wù)器

讓我們?cè)黾雍头?wù)器端的交互完成這個(gè)例子。現(xiàn)在我們還是應(yīng)編碼了兩行表格的數(shù) 據(jù),,現(xiàn)在讓我們通過(guò)ajax加載:

復(fù)制代碼
Ext.define('FWY.store.Students', { extend: 'Ext.data.Store', model: 'FWY.model.Student', autoLoad: true, proxy: { type: 'ajax', url: 'data/students.json', reader: { type: 'json', root: 'students', successProperty: 'success' } } });
復(fù)制代碼

這里我們?nèi)コ?'data' 屬性,,替換成 proxy ,代理是讓Store或者M(jìn)odel加載和保存數(shù)據(jù)的一個(gè)方式,,有AJAX,,JSONP,HTML5的localStorage本地存儲(chǔ)等,。這里我們使用了一個(gè)簡(jiǎn)單的AJAX代理,,讓它通過(guò)URL 'data/students.json' 加載數(shù)據(jù)。

我們同時(shí)給代理附加了一個(gè)reader,,reader是用來(lái)把服務(wù)器返回的數(shù)據(jù)解碼成Store能理解的格式,,這次我們使用了JSON reader,并且指定了root和 successProperty 配置(JSON reader的詳細(xì)配置看文檔),,最后我們創(chuàng)建一下數(shù)據(jù)文件 data/students.json ,,輸入內(nèi)容:

復(fù)制代碼
{ success: true, users: [ {id: 1, name: 'zhang', email: '[email protected]'}, {id: 2, name: 'lishi', email: '[email protected]'}   ] }
復(fù)制代碼

其他的變更就是我們給Store設(shè)置了 autoLoad 屬性并設(shè)置為 true ,這意味著Store生成之后會(huì)自動(dòng)讓Proxy加載數(shù)據(jù),,刷新?一下頁(yè)面應(yīng)該是看到和之前同樣的結(jié)果,,不同的是現(xiàn)在不是在程序中存在硬編碼數(shù)據(jù)了,最后的事情是將變更傳回服務(wù)器端,,這個(gè)例子中我們使用靜態(tài)的JSON文件,,沒(méi)有使用數(shù)據(jù)庫(kù),但足夠說(shuō)明我們例子的了,,首先做一點(diǎn)點(diǎn)變化告知proxy用于更新的url:

復(fù)制代碼
proxy: { type: 'ajax', api: { read: 'data/students.json', update: 'data/updateStudents.json', }, reader: { type: 'json', root: 'students', successProperty: 'success' } }
復(fù)制代碼

依然從 students.json 讀取數(shù)據(jù),,但是變更會(huì)發(fā)送到 updateStudents.json ,這里我們做?個(gè)模擬的應(yīng)答回包以讓我們知道程序可以正確工作,, updateStudents.json 只需要包含{'success':true},,其他要做的就是讓Store在編輯之后進(jìn)行同步,需要在 updateStudent 函數(shù)中增加一行代碼:

復(fù)制代碼
updateStudent: function(button) { var win = button.up('window'), form = win.down('form'), record = form.getRecord(), values = form.getValues(); record.set(values); win.close(); this.getStudentsStore().sync();//將數(shù)據(jù)同步到store中 }
復(fù)制代碼

最后附上本篇的代碼:點(diǎn)擊下載

--本篇完--

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多