<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
        博客園  :: 首頁  :: 新隨筆  :: 聯系 :: 訂閱 訂閱  :: 管理

      前言:

       

      實話實說,之前我是有些小瞧了Sencha Touch中的Device Profile的作用,所以在翻譯順序上才把它放在了比較靠后的位置。細讀此文之后才發現自己實在是大錯特錯,Device Profile簡直堪稱Sencha Touch MVC中的最大亮點之一。除非你甘愿放棄Sencha Touch那不可思議的跨設備能力,否則你都必須學透Device Profile這一功能。

       

      這篇文章的英文原址是 http://docs.sencha.com/touch/2-0/#!/guide/profiles

      原文標題是:Using Device Profiles應用程序中使用設備配置)

      Sencha Touch 交流QQ213119459歡迎您的加入。


       

      Using Device Profiles

      在應用程序中使用設備配置

      注:為方便起見,文中所有出現 Sencha Touch的地方均以 ST簡寫替代。


      Today's mobile web applications are expected to work on a wide variety of devices, spanning from the smallest mobile phones to the largest tablets. These devices have a wide range of screen resolutions and are used in different ways. People tend to use phone apps while out of the house to rapidly gather some information or perform some action - often in under a minute. Tablet apps are more likely to be used for longer periods of time, usually within the home or somewhere else they can sit for a long time.

      今日之移動web應用程序開發要求我們必須考慮盡可能廣泛的設備適用性,從最小的智能手機,到最大的平板電腦,不一而足。這些設備分辨率跨度很大而且使用方式千奇百怪。通常人們不在家的時候會使用手機應用來快速獲取信息或者做些別的什么,不過使用時間基本上都控制在一分鐘以內(譯者注:應該是每次一分鐘以內吧)。平板電腦的使用時間顯然就更長一些,而且一般使用場合是在家里或者在其他能夠長久安坐的什么地方。


      All of this means that people expect different app experiences on different devices. However, much of your application logic and assets can be shared between these different experiences. Writing separate apps for each platform is time consuming, error-prone and just plain boring. Thankfully, Device Profiles give us a simple way to share just as much code as we need to between device types while making it easy to customize behavior, appearance and workflows for each device.

      凡此總總意味著人們在不同的設備上期望的是不同的體驗,但事實上,盡管體驗不同,可應用程序的絕大部分邏輯和資源還是可以共享的。為每個平臺編寫一個獨立的app不僅浪費時間、容易出錯,而且還超級無聊。謝天謝地,設備配置(這一功能)給我們提供了一種簡單的方式,使得我們能夠共享盡可能多的代碼,同時又能輕松地為每種設備定制行為、外觀和工作流。


      Setting up Profiles

      配置內容


      Device Profiles exist within the context of an Application, for example if we want to create an email app with phone and tablet profiles we can define our app.js like this (see the Intro to Apps guide if this is not familiar):

      設備配置存在于應用程序的上下文環境之中,例如要創建一個帶有phonetablet配置的emal應用,我們可以像下面這樣來定義app.js(如果對此不熟悉的話請參考 Intro to Apps guide 


      Ext.application({

          name: 'Mail',

       

          profiles: ['Phone', 'Tablet']

      });


      We didn't give our Application a launch function, so at the moment all it is going to do is load those two Profiles. By convention, it expects to find these in app/profile/Phone.js and app/profile/Tablet.js. Here's what our Phone profile might look like:

      我們沒有給應用程序寫上launch方法,所以現在它唯一能做的就是加載這兩個Profiles。按照慣例,他們的存放路徑是app/profile/Phone.jsapp/profile/Tablet.js,看看Phone配置文件長得什么樣子吧:


      Ext.define('Mail.profile.Phone', {

          extend: 'Ext.app.Profile',

       

          config: {

              name: 'Phone',

              views: ['Main']

          },

       

          isActive: function() {

              return Ext.os.is.Phone;

          }

      });


      The Tablet profile follows the same pattern. In our Phone profile we only really supplied three pieces of information - the Profile name, the optional set of additional views to load if this Profile is activated, and an isActive function.

      Tablet的配置也是一樣的格式。這個Phone配置里面我們只提供了3條信息:Profile名稱,一組需要額外加載的視圖(該項屬于可選的),還有一個isActive函數。


      The isActive function is what determines if a given profile should be active on the device your app happens to be booting up on. By far the most common split is to create profiles for Phone and Tablet, using the built-in Ext.os.is.Phone and Ext.os.is.Tablet properties. You can write any code you like in the isActive function so long as it always returns true or false for the device it is running on.

      isActive這個函數將決定該profile在當前設備下是否被啟用。到目前為止,最常用的區分就是使用內置的Ext.os.is.PhoneExt.os.is.Tablet屬性,分別創建PhoneTabletprofile。你可以在isActive函數里面寫任何代碼,只要他最終能夠為當前設備返回一個true或者false即可。


      Determining the Active Profile

      當前活動配置


      Once the Profiles have been loaded, their isActive functions are called in turn. The first one to return true is the Profile that the Application will boot with. This Profile is then set to the Application's currentProfile, and the Application prepares to load all of its dependencies - the models, views, controllers and other classes that constitute the app. It does this by combining its own dependencies with those specified in the active profile.

      一旦Profile文件加載成功,它們的isActive函數會一次被調用。而應用程序將適配第一個返回trueprofile來啟動,該Profile隨即被設置成為應用程序的currentProfile,然后應用程序開始加載它所有的依賴項,包含數據模型、視圖、控制器和其他組成應用程序的一些類文件。


      For example, let's amend our Application so that it loads a few Models and Views of its own:

      看例子,我們改進一下剛才的應用程序,讓他加載一些數據模型和試圖進來:


      Ext.application({

          name: 'Mail',

       

          profiles: ['Phone', 'Tablet'],

       

          models: ['User'],

          views: ['Navigation', 'Login']

      });


      Now when we load the app on a phone, the Phone profile is activated and the application will load the following files:

      現在我們在手機上運行一下,Phone配置被激活,應用程序將加載如下文件:

      app/model/User.js
      app/view/Navigation.js
      app/view/Login.js
      app/view/phone/Main.js


      The first three items are specified in the Application itself - the User model plus the Navigation and Login views. The fourth item is specified by the Phone Profile and follows a special form. By convention, classes that are specific to a Profile are expected to be defined in a subdirectory with the same name as the Profile. For example, the 'Main' view specified in the Phone Profile will be loaded from app/view/phone/Main.js, whereas if we had defined 'Main' in the Application it would be loaded from app/view/Main.js.

      前三項(User數據模型以及NavigationLogin視圖)是應用程序自己定義的(也就是公共資源),第四項是Phone配置定義的。按照慣例,Profile定義的類將被放置在Profile同名的目錄下。比如,Phone配置定義的Main這個視圖就應該放在app/view/phone/Main.js文件中,如果Main是在應用程序中定義的話,就該放在app/view/Main.js中。

      The same applies to all of the models, views, controllers and stores loaded in a Profile. This is important as it enables us to easily share behavior, view logic and more between profiles (see the specializing views and controllers sections below). If you need to load classes that don't fit with this convention, you can specify the full class name instead:


      以上原則對Profile中加載的所有數據模型、視圖、控制器、數據存儲都適用。這樣做非常重要,因為這樣就能使得我們輕易地在不同設備之間共享行為、視圖、邏輯以及更多資源了,后面的章節你可以看到定制視圖和控制器的例子。如果想加載沒按照常規位置存放的類,你就得指定完整路徑了。


      Ext.define('Mail.profile.Phone', {

          extend: 'Ext.app.Profile',

       

          config: {

              name: 'Phone',

              views: ['Main', 'Mail.view.SpecialView'],

              models: ['Mail.model.Message']

          },

       

          isActive: function() {

              return Ext.os.is.Phone;

          }

      });


      As we see above, you can mix and match fully-qualified class names (e.g. 'Mail.view.SomeView') and relatively specified class names (e.g. 'Main', which becomes 'Mail.view.phone.Main'). Be aware that all models, views, controllers and stores specified for a Profile are treated this way. This means if there are Models or Stores that you want to load for Tablets only but do not want to make classes like Mail.model.tablet.User, you should specify the fully-qualified class names instead (e.g. Mail.model.User in this case).

      如上面代碼所示,你可以混合使用完整路徑調用方式(比如Mail.view.SomeView)和常規路徑調用方式(比如Main會被解析為Mail.view.phone.Main)。請注意所有在Profile中定義的數據模型、視圖、控制器、數據存儲都是這樣處理的。這也意味著如果你想加載一些數據模型和數據存儲卻不想讓它們的類名如Mail.model.tablet.User這樣,那就得指定完整的類名了(比如Mail.model.User)。


      The Launch Process

      Launch進程


      The launch process using Profiles is almost exactly the same as it is without Profiles. Profile-based apps have a 3-stage launch process; after all of the dependencies have been loaded, the following happens:

      Profile和沒有Profile的情況下,launch進程幾乎是一樣的。基于Profile構建的應用程序有3launch進程,當所有依賴項加載完成后,將會先后發生如下事件:


      Controllers are instantiated; each Controller's init function is called

      控制器被實例化,每個控制器的init方法被調用

      The Profile's launch function is called

      Profile中的launch方法被調用

      The Application's launch function is called.

      Application中的launch方法被調用


      When using Profiles it's common to use the Profile launch functions to create the app's initial UI. In many cases this means the Application's launch function is completely removed as the initial UI is usually different in each Profile (you can still specify an Application-wide launch function for setting up things like analytics or other profile-agnostic setup).

      當使用Profile的時候,通常會使用Profilelaunch方法去創建應用的初始界面,很多情況下意味著Applicationlaunch方法被徹底丟棄了,因為每一個Profile中的初始化UI通常是不同的。你依然可以指定一個跨profileapplication launch方法來初始化一些東西,比如分析數據或者其他。


      A typical Profile launch function might look like this:

      一個典型的Profile launch方法通常是這樣的:

      Ext.define('Mail.profile.Phone', {

          extend: 'Ext.app.Profile',

       

          config: {

              name: 'Phone',

              views: ['Main']

          },

       

          isActive: function() {

              return Ext.os.is.Phone;

          },

       

          launch: function() {

              Ext.create('Mail.view.phone.Main');

          }

      });


      Note that both Profile and Application launch functions are optional - if you don't define them they won't be called.

      注意ProfileApplicationlaunch方法都是可選的,如果你沒定義它們,就不會被調用。


      Specializing Views

      專用視圖


      Most of the specialization in a Profile occurs in the views and the controllers. Let's look at the views first. Say we have a Tablet Profile that looks like this:

      Profile大部分的專用設置都發生在視圖和控制器上。先看視圖,假定我們有一個如下的Tablet配置:


      Ext.define('Mail.profile.Tablet', {

          extend: 'Ext.app.Profile',

       

          config: {

              views: ['Main']

          },

       

          launch: function() {

              Ext.create('Mail.view.tablet.Main');

          }

      });


      When we boot this app up on a tablet device, the file app/views/tablet/Main.js will be loaded as usual. Here's what we have in our app/views/tablet/Main.js file:

      當我們在平板電腦上啟動這個應用程序時,app/views/tablet/Main.js這個文件將被加載,其內容如下:


      Ext.define('Mail.view.tablet.Main', {

          extend: 'Mail.view.Main',

       

          config: {

              title: 'Tablet-specific version'

          }

      });


      Usually when we define a view class we extend one of Sencha Touch's built in views but in this case we're extending Mail.view.Main - one of our own views. Here's how that on looks:

      通常我們定義一個視圖的時候都會擴展某一個ST內置的視圖,但是這個例子當眾,我們擴展的是Mail.view.Main這個我們自己創建的視圖,代碼如下:


      Ext.define('Mail.view.Main', {

          extend: 'Ext.Panel',

       

          config: {

              title: 'Generic version',

              html: 'This is the main screen'

          }

      });


      So we have a superclass (Mail.view.Main) and a Profile-specific subclass (Main.view.tablet.Main) which can customize any aspect of the superclass. In this case we're changing the title of the Main view from "Generic version" to "Tablet-specific version" in our subclass, so when our app launches that's what we will see.

      這樣我們就有了一個父類(Mail.view.Main)和一個Profile指定的子類(Main.view.tablet.Main),在子類中我們可以定制任何內容。這個例子里我們在子類中把它的標題從Generic version改成Tablet-specific version,當應用運行起來的時候你就會看到了。


      Because these are just normal classes it's easy to customize almost any part of the superclass using the flexible config system. For example, let's say we also have a phone version of the app - we could customize its version of the Main view like this (app/view/phone/Main.js):

      由于這都是些常規的類,所以我們通過伸縮性極強的config系統可以很容易定制子類中的任何部分。假設我們這個應用還有一個phone版本,我們將會在其中(app/view/phone/Main.js)像這樣來定制他的版本。


      Ext.define('Mail.view.phone.Main', {

          extend: 'Mail.view.Main',

       

          config: {

              title: 'Phone-specific version',

       

              items: [

                  {

                      xtype: 'button',

                      text: 'This is a phone...'

                  }

              ]

          }

      });

       

      Sharing sub views

      共享子視圖


      While the above is useful, it's more common to share certain pieces of views and stitch them together in different ways for different profiles. For example, imagine an email app where the tablet UI is a split screen with a message list on the left and the current message loaded on the right. The Phone version is the exact same message list and a similar message view, but this time in a card layout as there is not enough screen space to see them both simultaneously.

      上面的例子很有用,不過更常見的是共享視圖中的特定部分并在不同的profile中以不同的形式把它們拼合在一起。例如一個email應用,在平板電腦上的界面應該是左右分屏左側放置郵件列表右側顯示當前加載郵件的內容,而手機版本同樣是一個郵件列表和類似的內容視圖,但這次他們只能通過card布局來擺放(這就意味著顯示一個,隱藏另一個),因為顯然手機上沒有足夠的屏幕空間來同時顯示兩者。


      To achieve this we'd start off creating the two shared sub views - the message list and the message viewer. In each case we've left the class config out for brevity:

      要實現這一設想我們得先創建兩個共享子視圖:一個郵件列表和一個內容瀏覽器,下面例子里我們將省略類的config


      Ext.define('Main.view.MessageList', {

          extend: 'Ext.List',

          xtype: 'messagelist',

       

          //config goes here...

      });


      And the Message Viewer:

      下面是內容瀏覽器:


      Ext.define('Main.view.MessageViewer', {

          extend: 'Ext.Panel',

          xtype: 'messageviewer',

       

          //config goes here...

      });


      Now, to achieve our target layout the tablet Main view might do something like this:

      然后要達到目的我們得在tabletmain視圖里我們要這樣布局:


      Ext.define('Main.view.tablet.Main', {

          extend: 'Ext.Container',

       

          config: {

              layout: 'fit',

              items: [

                  {

                      xtype: 'messagelist',

                      width: 200,

                      docked: 'left'

                  },

                  {

                      xtype: 'messageviewer'

                  }

              ]

          }

      });


      This will create a 200px wide messagelist on the left, and use the rest of the device's screen space to show the message viewer. Now let's say we want to achieve our Phone layout:

      以上代碼將在屏幕左側創建一個200像素寬的郵件列表,然后把內容瀏覽器放在屏幕剩余的區域,下面我們要實現手機布局了:


      Ext.define('Main.view.phone.Main', {

          extend: 'Ext.Container',

       

          config: {

              layout: 'card',

              items: [

                  {

                      xtype: 'messagelist'

                  },

                  {

                      xtype: 'messageviewer'

                  }

              ]

          }

      });


      In this case we're just using a Container with a card layout (a layout that only shows one item at a time), and putting both the list and the viewer into it. We'd need to plug in some logic that tells the Container to show the messageviewer when a message in the list is tapped on, but we've very easily reused our two sub views in different configurations based on which Profile is loaded.

      這種情況下我們只需要使用一個card布局(每次只顯示其子項中的一個),然后把列表視圖和內容瀏覽視圖放置其中。我們還需要加入一些邏輯代碼來告訴容器當列表中的某一項被點擊時應該如何去顯示內容瀏覽視圖,但是我們已經非常輕易地在不同Profile的不同配置中復用了兩個子視圖。


      As before, we also have the option to customize the two shared views for each Profile - for example we could create Mail.view.phone.MessageViewer and Mail.view.tablet.MessageViewer subclasses, both of which extend the Mail.view.MessageViewer superclass. This enables us to again share a lot of view code between those classes while presenting customizations appropriate for the device the user happens to be using.

      像前面所做的那樣,我們同樣可以選擇分別為每個Profile定制共享視圖,比如創建Mail.view.phone.MessageViewerMail.view.tablet.MessageViewer兩個子類,他們都繼承自Mail.view.MessageViewer這個父類。這樣使得我們可以再次共享很多視圖代碼。


      Specializing Controllers

      定制控制器


      Just like with Views, many applications have a lot of Controller logic that can be shared across multiple Profiles. The biggest differences here between profiles are usually workflow-related. For example, an app's tablet profile may allow you to complete a workflow on a single page whereas the phone profile presents a multi-page wizard.

      跟視圖一樣,很多應用程序同樣有很多控制器邏輯可以跨配置共享。他們最大的區別通常是操作流不一致,例如一個應用程序的平板profile可以允許你在一個頁面上完成工作,而相同的內容在手機profile中得通過多頁式的的向導來進行展現。


      Here we have a simple Phone profile that loads a view called Main and a controller called Messages. As before, this will load app/view/phone/Main.js and app/controller/phone/Messages.js:

      這里有一個簡單的手機profile,它加載了一個叫做Main的視圖和一個叫做Messages的控制器。顯然,這將加載pp/view/phone/Main.jsapp/controller/phone/Messages.js兩個文件:


      Ext.define('Mail.profile.Phone', {

          extend: 'Ext.app.Profile',

       

          config: {

              views: ['Main'],

              controllers: ['Messages']

          },

       

          launch: function() {

              Ext.create('Mail.view.phone.Main');

          }

      });


      Now, we know that our phone and tablet-specific controllers share most of their functionality so we'll start by creating a controller superclass in app/controller/Messages.js:

      現在我們知道手機和平板電腦上的控制器大部分功能都是一樣的,所以我們在app/controller/Messages.js文件中先創建一個控制器的父類:


      Ext.define('Mail.controller.Messages', {

          extend: 'Ext.app.Controller',

       

          config: {

              refs: {

                  viewer: 'messageviewer',

                  messageList: 'messagelist'

              },

              control: {

                  messageList: {

                      itemtap: 'loadMessage'

                  }

              }

          },

       

          loadMessage: function(item) {

              this.getViewer().load(item);

          }

      });


      This Controller does 3 things:

      這個控制器做了三件事:


      Sets up refs to views that we care about

      設置了視圖上我們需要使用到的refs

      Listens for the itemtap event on the message list and calls the loadMessage function when itemtap is fired

      偵聽列表上的itemtap事件,當事件被觸發時調用loadMessage方法

      Loads the selected message item into the Viewer when loadMessage is called

      loadMessage被調用時,加載被選中的消息到內容瀏覽器


      Now that we have this, it's easy to create our phone-specific controller:

      現在我們很容易創建手機的專用控制器:


      Ext.define('Mail.controller.phone.Messages', {

          extend: 'Mail.controller.Messages',

       

          config: {

              refs: {

                  main: '#mainPanel'

              }

          },

       

          loadMessage: function(item) {

              this.callParent(arguments);

              this.getMain().setActiveItem(1);

          }

      });


      Here we're extending the Messages superclass controller and providing 2 pieces of functionality:

      這里擴展了Messages父類控制器并增加了兩個小功能:


      We add another ref for the phone UI's main panel

      為手機界面的主面板增加了一個ref

      We extend the loadMessage function to perform the original logic and then set the main panel's active item to the message viewer

      我們擴展了loadMessage功能,首先執行父類既有的邏輯然后把內容瀏覽器視圖設為active


      All of the configuration that was in the superclass is inherited by the subclass. In the case of duplicated configs like refs, the config is merged, so the phone Messages controller class has 3 refs - main, viewer and messageList. Just as with any other class that extends another, we can use callParent to extend an existing function in the superclass.

      所有父類中的配置都會被子類繼承。所以像refs這種在config中重復出現的配置屬性,它們會被合并,也就是說手機的Messages控制器就會有3refsmainviewermessageList)。就像其它的繼承一樣,我們通過callParent來擴展一個父類中已經存在的函數。


      Bear in mind that our Mail.controller.Messages superclass is not declared as a dependency by either the Application or the Profile. It it automatically loaded because our Mail.controller.phone.Messages controller extends it.

      記住Mail.controller.Messages這個父類既不需要在Application中進行依賴聲明,也無需在Profile中聲明,它會自動被加載,因為Mail.controller.phone.Messages控制器繼承了它。


      What to Share

      共享什么


      In the example above we were able to share some (but not all) of our refs. We were also able to share the single event that we listen for with the Controller's control config. Generally speaking, the more the app diverges between profiles, the fewer refs and control configs you will be able to share.

      前面例子當眾我們能夠共享一部分refs(但不是全部),我們也能夠共享一個在控制器的control中設置了偵聽的事件。總的來說,應用程序不同Profile之間的區別越大,能共享的refscontrolconfig也就越少。


      The one Controller config that should be shared across profiles is routes. These map urls to controller actions and allow for back button support and deep linking. It's important to keep the routes in the superclass because the same url should map to the same content regardless of the device.

      有一個應該被不同profile共享的控制器configroute,這些url被映射到控制器動作并被允許支持后退按鈕和深度鏈接。在父類中定義route是很重要的,因為不論在哪個設備上,同樣的url總應該被映射到同樣的內容。


      For example, if your friend is using the phone version of your app and sends you a link to the page she is currently on within your app, you should be able to tap that link on your tablet device and see the tablet-specific view for that url. Keeping all routes in the superclass enables you to keep a consistent url structure that will work regardless of device.

      例如,你的朋友使用了應用程序的phone版本,然后發送給你一個他正在看的頁面鏈接,當你在平板電腦上點擊了這個鏈接之后,你看到的內容也應該是一樣的,只不過是tablet專用的視圖展示形式而已。確保所有的route都在父類里使得你可以保證url架構的一致性并無需關注是在什么設備上。


      Specializing Models

      專用的數據模型


      Models are customized per Profile less frequently than Controllers and Views, so don't usually require a subclass. In this case we just specify the fully qualified class names for models:

      每個Profile定制不同的數據模型這種情況比定制控制器和視圖出現的要少,所以一般不需要用子類,在這里我們僅僅指定完整的類名稱就可以了。


      Ext.define('Mail.profile.Tablet', {

          extend: 'Ext.app.Profile',

       

          config: {

              models: ['Mail.model.Group']

          }

      });

      主站蜘蛛池模板: 亚洲高清无在码在线无弹窗| 国产精品亚韩精品无码a在线| 亚洲第一香蕉视频啪啪爽| 国产午夜福利精品视频| 四虎影视国产精品永久在线| 国模冰莲自慰肥美胞极品人体图| 日韩av一区二区三区在线| 国产精品SM捆绑调教视频 | 老男人久久青草av高清| 亚洲精品网站在线观看不卡无广告| 四虎精品视频永久免费| 色综合视频一区二区三区| 熟女人妻精品一区二区视频| 亚洲成av人片乱码色午夜| 野花香电视剧免费观看全集高清播放 | 国产玖玖视频| 亚洲国产性夜夜综合 | 亚洲VA成无码人在线观看天堂| 国产老熟女视频一区二区| 91超碰在线精品| 2020国产欧洲精品网站| 国产偷人爽久久久久久老妇app| 亚洲国产青草衣衣一二三区| 亚洲国产精品成人无码区| 日韩人妻一区中文字幕| 亚洲欧洲日韩国内精品| 人妻精品动漫H无码中字| 成年女人黄小视频| 欧美牲交a欧美牲交aⅴ一| 欧美人与动牲猛交A欧美精品| 无码av中文一区二区三区桃花岛| 国产精品色三级在线观看| 桃花岛亚洲成在人线AV| 97午夜理论电影影院| 久久精品日韩av无码| 国产精品久久毛片av大全日韩| 亚洲综合久久精品国产高清| 奇米四色7777中文字幕| 不卡乱辈伦在线看中文字幕| 久人人爽人人爽人人片av| 久久91精品牛牛|