Sencha Touch 2 官方文檔翻譯之 Managing Dependencies with MVC(管理MVC依賴項(xiàng))
Posted on 2012-03-13 21:23 隨它去吧 閱讀(3840) 評(píng)論(0) 收藏 舉報(bào)
如果你第一次看Sencha Touch MVC應(yīng)用程序的例子,很可能會(huì)被那一個(gè)個(gè)文件夾和一堆堆js文件搞得頭昏腦脹,它們之間到底有什么關(guān)系?互相之間如何協(xié)作?這就是你在下手寫代碼之前必須搞清楚的第一件事了,本專題將為你解決這個(gè)困惑。
這篇文章的英文原址是 http://docs.sencha.com/touch/2-0/#!/guide/mvc_dependencies
原文標(biāo)題是:Managing Dependencies with MVC(管理MVC依賴項(xiàng))。
Sencha Touch 交流QQ群213119459歡迎您的加入。
Managing Dependencies with MVC
管理MVC依賴項(xiàng)
注:為方便起見,文中所有出現(xiàn) Sencha Touch的地方均以 ST簡(jiǎn)寫替代。
There are two main places that dependencies can be defined in a Sencha Touch 2 app - on the application itself or inside the application classes. This guide gives some advice on how and where to declare dependencies in your app.
ST2應(yīng)用程序用來定義依賴項(xiàng)的地方主要有兩個(gè),application本身和應(yīng)用程序內(nèi)部類。本指南將給出一些關(guān)于應(yīng)用程序如何放置和在哪里放置依賴項(xiàng)的建議。
Application Dependencies
應(yīng)用程序依賴項(xiàng)
When you create an MVC application, your Ext.application gives you a convenient way of specifying the models, views, controllers, stores and profiles that your application uses. Here's an example:
當(dāng)你創(chuàng)建一個(gè)MVC應(yīng)用程序時(shí),Ext.application會(huì)提供一個(gè)直觀的方式來設(shè)置應(yīng)用程序會(huì)用到的數(shù)據(jù)模型、視圖、控制器、數(shù)據(jù)存儲(chǔ)器和配置文件等,如下例所示:
Ext.application({
name: 'MyApp',
views: ['Login'],
models: ['User'],
controllers: ['Users'],
stores: ['Products'],
profiles: ['Phone', 'Tablet']
});
These 5 configuration options are convenient ways to load the types of files that applications usually consist of - models, views, controllers, stores and profiles. Specifying these configurations means your application will automatically load the following files:
這5個(gè)配置項(xiàng)是用來加載應(yīng)用程序常用文件(數(shù)據(jù)模型、視圖、控制器、存儲(chǔ)器、配置文件)的快捷方式。如上的配置意味著應(yīng)用程序會(huì)自動(dòng)加載下列文件:
app/view/Login.js
app/model/User.js
app/controller/Users.js
app/store/Products.js
app/profile/Phone.js
app/profile/Tablet.js
In terms of what gets loaded, the example above is equivalent to defining dependencies manually like this:
就加載文件而言,上面的例子跟下面的定義是等價(jià)的:
Ext.require([
'MyApp.view.Login',
'MyApp.model.User',
'MyApp.controller.Users',
'MyApp.store.Products',
'MyApp.profile.Phone',
'MyApp.profile.Tablet'
]);
As you add more classes to your application, these configurations become more and more useful in helping you avoid typing out the full class names for every file. Be aware, however, that three of those configurations do more than just load files. As well as loading the files, they do the following:
在你需要加載更多的類文件情況下,這種配置方式就會(huì)更有用,它能避免你為每一個(gè)文件都拼寫又臭又長(zhǎng)的完整類名。除了把依賴文件加載進(jìn)來之外,這幾個(gè)配置還會(huì)做更多的事情:
l profiles - instantiates each Profile and determines if it should be active. If so, the Profile's own dependencies are also loaded
配置文件 – 實(shí)例化每一個(gè)Profle并判斷哪一個(gè)當(dāng)前可用。當(dāng)前可用的那個(gè)profile中所有依賴項(xiàng)也將被加載
l controllers - instantiates each Controller after loading
控制器 – 加載完成后實(shí)例化每一個(gè)控制器
l stores - instantiates each Store, giving it a default store ID if one is not specified
存儲(chǔ)器 – 實(shí)例化每一個(gè)存儲(chǔ)器,沒有指定id的存儲(chǔ)器會(huì)被指定一個(gè)默認(rèn)id
What this means is that if you want to take advantage of all of the convenience MVC offers you, you're advised to use these configuration options when defining your application dependencies.
這意味著,如果你要享受MVC帶給你的便利,那么載你定義應(yīng)用程序依賴項(xiàng)的時(shí)候,最好使用配置選項(xiàng)這種方式。
Profile-specific Dependencies
配置文件指定的依賴項(xiàng)
When using Device Profiles, chances are it means you have some classes that are used only on certain devices. For example, the Tablet version of your app probably contains more functionality than the Phone version, which usually means it will need to load more classes. Additional dependencies can be specified inside each Profile:
當(dāng)你使用設(shè)備配置的時(shí)候,可能會(huì)有一些類是僅在特定設(shè)備上使用的。例如,平板電腦版本的應(yīng)用程序可能包含比手機(jī)版本更多的功能,這當(dāng)然意味著要加載更多的類。每個(gè)Profile都可以在內(nèi)部定義額外的依賴項(xiàng)。
Ext.define('MyApp.profile.Tablet', {
extend: 'Ext.app.Profile',
config: {
views: ['SpecialView'],
controllers: ['Main'],
models: ['MyApp.model.SuperUser']
},
isActive: function() {
return Ext.os.is.Tablet;
}
});
Now what's going to happen here is that the dependencies specified in each Profile are going to be loaded regardless of whether or not the Profile is active. The difference is, even though they're loaded, the Application knows not to do the additional processing like instantiating profile-specific Controllers if the profile is not active.
然后每個(gè)profile中定義的依賴項(xiàng)都會(huì)被加載,不管這個(gè)profile是否active,不過盡管都被加載,但應(yīng)用程序不會(huì)去做類似實(shí)例化非active狀態(tài)profile指定的控制器這樣的無用功。
This probably sounds counter-intuitive - why download classes that aren't going to be used? The reason we do this is to produce a universal production build that can be deployed to any device, detect which profile it should use and then boot the app. The alternative is to create custom builds for each profile, craft a micro-loader than can detect which profile a device should activate and then download the code for that profile.
這聽起來有點(diǎn)不合常規(guī),為什么要下載那些不會(huì)用到的類文件呢?這么做的原因是產(chǎn)生一個(gè)可以在任何設(shè)備上運(yùn)行的通用程序版本,然后檢測(cè)哪一個(gè)profile應(yīng)該被使用,接著從這個(gè)profile啟動(dòng)應(yīng)用程序。與之相對(duì)的選擇是為每個(gè)profile創(chuàng)建一個(gè)應(yīng)用版本,然后啟動(dòng)一個(gè)微型加載器來檢測(cè)哪個(gè)profile該被選擇,然后去下載該profile需要的代碼文件。
While the universal build approach does mean you're downloading code you don't need on every device, for the vast majority of apps this amounts to so little additional size it's difficult to detect the difference. For very large apps the difference will become more noticeable so it's possible we'll revisit this subject after 2.0.
的確這種通用架構(gòu)的程序會(huì)在每個(gè)設(shè)備上都下載一些根本用不到的代碼文件,不過對(duì)于絕大多數(shù)應(yīng)用程序來說,你多下載的這點(diǎn)文件影響實(shí)在是微乎其微。而對(duì)于比較龐大的應(yīng)用程序來說,這個(gè)問題可能更值得注意,所以我們可能在2.0的后續(xù)版本對(duì)它進(jìn)行處理。
Nested Dependencies
級(jí)聯(lián)依賴
For larger apps it's common to split the models, views and controllers into subfolders so keep the project organized. This is especially true of views - it's not unheard of for large apps to have over a hundred separate view classes so organizing them into folders can make maintenance much simpler.
大一些應(yīng)用通常會(huì)把數(shù)據(jù)模型、視圖、控制器分別存儲(chǔ)在不同子文件夾下,這樣可以讓整個(gè)項(xiàng)目看起來更清晰明了一些。對(duì)于視圖來說尤其如此,大型應(yīng)用擁有上百個(gè)獨(dú)立的視圖類并非天方夜譚,因此分文件夾存儲(chǔ)幾乎不可避免。
To specify dependencies in subfolders just use a period (".") to specify the folder:
指定子文件夾中的依賴項(xiàng)只需要使用“.”來分割文件夾路徑即可:
Ext.application({
name: 'MyApp',
controllers: ['Users', 'nested.MyController'],
views: ['products.Show', 'products.Edit', 'user.Login']
});
In this case these 5 files will be loaded:
上例中將會(huì)加載下列5個(gè)文件
app/controller/Users.js
app/controller/nested/MyController.js
app/view/products/Show.js
app/view/products/Edit.js
app/view/user/Login.js
Note that we can mix and match within each configuration here - for each model, view, controller, profile or store you can specify either just the final part of the class name (if you follow the directory conventions), or the full class name.
我們可以混合使用兩種方式來定義每個(gè)數(shù)據(jù)模型、視圖、控制器、配置文件和存儲(chǔ)器:快捷路徑方式(符合mvc推薦原則的類只寫最后的類名即可)和完整路徑方式(自定義路徑的類則寫完整路徑加類名)。
External Dependencies
外部依賴項(xiàng)
We can specify application dependencies from outside our application by fully-qualifying the classes we want to load. A common use case for this is sharing authentication logic between multiple applications. Perhaps you have several apps that login via a common user database and you want to share that code between them. An easy way to do this is to create a folder alongside your app folder and then add its contents as dependencies for your app.
我們可以通過指定想要加載的完整類名方式來定義應(yīng)用程序之外的類作為依賴項(xiàng)。這種情況最常見的用途就是在多個(gè)應(yīng)用之間共享認(rèn)證邏輯。我們可能會(huì)有好幾個(gè)應(yīng)用程序都要到同一個(gè)用戶數(shù)據(jù)庫(kù)進(jìn)行驗(yàn)證并實(shí)現(xiàn)登錄,這時(shí)我們當(dāng)然希望它們能夠共享用戶登錄的代碼。比較容易的方式就是在應(yīng)用程序文件夾之外創(chuàng)建一個(gè)單獨(dú)的文件夾然后把其中的內(nèi)容作為依賴項(xiàng)添加到應(yīng)用程序中去。
For example, let's say our shared login code contains a login controller, a user model and a login form view. We want to use all of these in our application:
我們假定共享的登錄代碼包含一個(gè)login控制器,一個(gè)用戶model和一個(gè)login表單視圖。我們要在應(yīng)用程序中把它們?nèi)坑蒙希?/span>
Ext.Loader.setPath({
'Auth': 'Auth'
});
Ext.application({
views: ['Auth.view.LoginForm', 'Welcome'],
controllers: ['Auth.controller.Sessions', 'Main'],
models: ['Auth.model.User']
});
This will load the following files:
上述代碼將加載以下的文件:
Auth/view/LoginForm.js
Auth/controller/Sessions.js
Auth/model/User.js
app/view/Welcome.js
app/controller/Main.js
The first three were loaded from outside our application, the last two from the application itself. Note how we can still mix and match application files and external dependency files.
前面三個(gè)文件加載自應(yīng)用程序外部,后兩個(gè)則來自應(yīng)用程序內(nèi)部。同樣我們可以混合調(diào)用內(nèi)外部依賴項(xiàng)。
Note that to enable the loading of external dependencies we just have to tell the Loader where to find those files, which is what we do with the Ext.Loader.setPath call above. In this case we're telling the Loader to find any class starting with the 'Auth' namespace inside our 'Auth' folder. This means we can drop our common Auth code into our application alongside the app folder and the framework will be able to figure out how to load everything.
想要啟用外部依賴項(xiàng)加載,我們只需告訴Loader到哪里可以找到這些文件即可,Ext.Loader.setPath就是干這個(gè)的。上例中我們告訴Loader所有以Auth命名空間中的文件都可以到Auth這個(gè)文件夾中找到。這樣我們就能把應(yīng)用程序文件夾之外的通用驗(yàn)證代碼都拽進(jìn)來了,其他的事情由ST框架來處理。
Where Each Dependency Belongs
依賴項(xiàng)應(yīng)該放在哪里
The general rule when deciding where to declare each dependency is to keep your classes completely self-contained. For example, if you have a view that contains several other views, you should declare those dependencies inside the view class, not the application:
決定在哪里聲明依賴項(xiàng)的一個(gè)基本原則就是保證你的類文件完整的內(nèi)部包含。例如,你有一個(gè)視圖A包含了幾個(gè)其他的視圖,你就應(yīng)該在這個(gè)A視圖內(nèi)部聲明它的依賴項(xiàng),而不是在application中:
Ext.define('MyApp.view.Main', {
extend: 'Ext.Container',
requires: [
'MyApp.view.Navigation',
'MyApp.view.MainList'
],
config: {
items: [
{
xtype: 'navigation'
},
{
xtype: 'mainlist'
}
]
}
});
And in your app.js:
App.js中這么寫:
Ext.application({
views: ['Main']
});
This is the best way to declare those dependencies for two reasons - it keeps your app.js clean and enables you to reliably require your MyApp.view.Main and know that it already has all of its dependencies satisfied. The alternative would be to list all of your views inside your app.js like this:
這才是依賴項(xiàng)的最佳聲明方式。兩個(gè)原因:1、確保app.js干凈;2、讓你知道主程序依賴MyApp.view.Main就已經(jīng)足夠。不好的方式就是下面這樣把視圖都羅列在app.js里:
//this is bad
Ext.application({
views: ['Main', 'Navigation', 'MainList']
});
A simple way of thinking about this is that app.js just contains top-level views. If you use Ext.create('MyApp.view.SomeView') inside your app, that view can be considered top-level. If a view is only ever constructed as a sub-view of another view (as with MyApp.view.Navigation and MyApp.view.MainList above), it doesn't belong in app.js.
換種方式來描述這個(gè)問題,app.js只需要包含最頂級(jí)的視圖即可。你在應(yīng)用程序內(nèi)部通過Ext.create('MyApp.view.SomeView')來創(chuàng)建的視圖就可以視作頂級(jí)視圖。其他那些僅僅被作為某些視圖內(nèi)部子視圖的(比如例子中的MyApp.view.Navigation和MyApp.view.MainList)就不應(yīng)該出現(xiàn)在app.js里面。
Changes since 1.x
跟1.x版本的不同之處
In Sencha Touch 1, dependencies were often specified in Controllers as well as in the Ext.application call. While this offered some conveniences, it also masked the true architecture of the system and coupled views, models and stores too closely to controllers. Here's what you could do in 1.x:
在ST1中,依賴項(xiàng)經(jīng)常在控制器中指定(就跟Ext.application中那樣)。這樣的確提供了一些便利,但同時(shí)也模糊了系統(tǒng)的真實(shí)架構(gòu),而且視圖、數(shù)據(jù)模型和數(shù)據(jù)存儲(chǔ)器與控制器之間靠得太緊密。在1.x中我們是這么做的:
//1.x code, deprecated
Ext.regController('SomeController', {
views: ['Login'],
models: ['User'],
stores: ['Products']
});
This is exactly the same as defining the views, models and stores inside Ext.application, but also gave some convenience methods for accessing those classes inside your controller. 1.x generated two functions - getLoginView() and getUserModel() - and exposed a getStore() function that returned a reference to any of the Stores you defined in this Controller. In 2.x these functions no longer exist, but it's easy to use the alternatives.
這種方式跟Ext.application中定義視圖、數(shù)據(jù)模型和數(shù)據(jù)存儲(chǔ)器是一樣的,這么做的確也為控制器內(nèi)部訪問這些類提供了很方便的方法。ST1.x框架會(huì)自動(dòng)產(chǎn)生兩個(gè)方法getLoginView()和getUserModel(),還有一個(gè)getStore()函數(shù)可以返回對(duì)控制器中定義的任意數(shù)據(jù)存儲(chǔ)器的引用。在ST2.x中這些函數(shù)都不復(fù)存在,但是也提供了很便利的方法。
In each case here the first line refers to Sencha Touch 1.x, with the second line showing the 2.x way:
下面例子的第一行是ST1.x的寫法,第二行是ST2.x的寫法:
//creating a view - 2.x uses the standardized Ext.create
this.getLoginView().create();
Ext.create('MyApp.view.Login');
//getting a Model - just type out the Model name (it's shorter and faster)
this.getUserModel();
MyApp.model.User;
//Ext.getStore can access any Store whereas the old this.getStore only
//accessed those Stores listed in your Controller
this.getStore('Products');
Ext.getStore('Products');
Removing these functions speeds up application launching because the framework no longer needs to generate one function for each model and view defined in each Controller. It also means that the conventions for MVC match the conventions for the rest of the framework, leading to a more predictable API.
去掉這些方法加速了應(yīng)用程序的運(yùn)行速度,因?yàn)?span lang="EN-US">ST框架無需再為控制器中的每個(gè)視圖和數(shù)據(jù)模型來生成一個(gè)方法了。這就意味著使用MVC的便利之處同樣也對(duì)其他框架有效,從而使得整個(gè)API更加受控。
浙公網(wǎng)安備 33010602011771號(hào)