Sencha Touch 2 官方文檔翻譯之 Using Views in your Applications(使用視圖)


前言: 

視圖[View]是MVC應用程序的臉面,不管你的應用程序設計如何,用戶都只能看到眼前的視圖,因此對你的評價也只能通過對視圖的體驗來得到。因此無論如何,一定要用心去設計你的視圖。 

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

原文標題是:Using Views in your Applications應用程序中使用視圖)。在官方文檔目錄中,它事實上的地位是MVC概述之后開篇三板斧之一,鑒於Sencha Touch MVC的特點,這三板斧的介紹順序是倒過來的,先C控制器再V視圖最后才是M數據模型,但是其重要性卻不分先后。

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

 

 

Using Views in your Applications

在應用程序中使用視圖

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

From the user's point of view, your application is just a collection of views. Although much of the value of the app is in the Models and Controllers, the Views are what the user interacts with directly. In this guide we're going to look at how to create the views that build your application.

從用戶的視角來看,你的應用程序就是一堆視圖的集合,盡管應用程序大部分有價值的東西都在數據模型和控制器里,但視圖才是直接跟用戶互動的東西。這篇指南將帶我們學習如何創建視圖來搭建應用程序。 


Using Existing Components

使用現存組件

The easiest way to create a view is to just use Ext.create with an existing Component. For example, if we wanted to create a simple Panel with some HTML inside we can just do this:

最簡單的方法是使用Ext.create來創建一個ST中現存的內置組件,這同樣也是一個視圖。例如我們只想要創建一個包含簡單html代碼的Panel,我們可以這么做:

Ext.create('Ext.Panel', {

    html: 'Welcome to my app',

    fullscreen: true

});

 
This simply creates a Panel with some html and makes it fill the screen. You can create any of our built-in components this way but best practice is to create a subclass with your specializations and then create that. Thankfully that's simple too:

上述例子將會創建一個包含html代碼的Panel並使其充滿屏幕。你可以用這種方法創建任意內置組件,不過最好的方式還是專門創建一個(內置組件的)子類,然后再來創建這個(定制后的)子類的實例。幸好這也不是什么麻煩事兒。

Ext.define('MyApp.view.Welcome', {

    extend: 'Ext.Panel', 

    config: {

        html: 'Welcome to my app',

        fullscreen: true

    }

}); 

Ext.create('MyApp.view.Welcome');

 
The outcome is the same, but now we have a brand new component that we can create any number of times. This is the pattern we'll normally want to follow when building our app - create a subclass of an existing component then create an instance of it later. Let's take a look through what we just changed:

上述代碼的結果是一樣的,但是我們現在有了一個自己命名的新組件,而且以后我們還可以多次使用這個新組件。這才是我們推薦的應用開發模式:創建一個現存組件的子類然后再創建該子類的實例。我們來看一下這種方式跟前面相比有哪些變化:

  • Ext.define allows us to create a new class, extending an existing one (Ext.Panel in this case) 
    Ext.define允許我們通過繼承一個存在的類(此例中是Ext.Panel)來創建一個新類。
  • We followed the MyApp.view.MyView convention for our new view class. You can name it whatever you like but we suggest sticking with convention 
    遵循MyApp.view.MyView的常規來給新視圖命名,我們也推薦你這樣做,而不要隨心所欲
  • We defined config for the new class inside a config object 
    我們使用config對象為新類定義它自己的參數

 
Any of the config options available on Ext.Panel can now be specified in either our new class's config block or when we come to create our instance. When defining a subclass be sure to use the config object, when creating just pass in an object.

此時Ext.Panel的所有有效config屬性都可以在新類的config配置塊中進行定義或者在創建實例時傳入使用了。定義子類的時候務必使用config對象(其實就是用{}包裹的一系列配置參數的集合),創建的時候也可以傳入一個config對象集合。

For example, here's the same code again but with additional configuration passed in with our Ext.create call:

下面的例子只在剛才代碼基礎之上,在Ext.create時傳入了一個新的配置參數。

Ext.define('MyApp.view.Welcome', {

    extend: 'Ext.Panel', 

    config: {

        html: 'Welcome to my app',

        fullscreen: true

    }

}); 

Ext.create('MyApp.view.Welcome', {

    styleHtmlContent: true

}); 


A Real World Example

一個更貼近現實的例子

This is one of the view classes from our Twitter app:

這個視圖類來自於我們的Twitter應用:

Ext.define('Twitter.view.SearchBar', {

    extend: 'Ext.Toolbar',

    xtype : 'searchbar',

    requires: ['Ext.field.Search'], 

    config: {

        ui: 'searchbar',

        layout: 'vbox',

        cls: 'big', 

        items: [

            {

                xtype: 'title',

                title: 'Twitter Search'

            },

            {

                xtype: 'searchfield',

                placeHolder: 'Search...'

            }

        ]

    }

});

 
This follows the same pattern as before - we've created a new class called Twitter.view.SearchBar, which extends the framework's Ext.Toolbar class. We also passed in some configuration options, including a layout and an items array.

它遵循前面提到的規則,創建了一個繼承框架Ext.Toolbar類的新子類,命名為Twitter.view.SearchBar,我們給它傳入一些配置參數,其中包含了一個layout屬性和items數組。

We've used a couple of new options this time:

這次我們使用了兩個新的參數:

  • requires - because we're using a searchfield in our items array, we tell our new view to require the Ext.field.Search class. At the moment the dynamic loading system does not recognize classes specified by xtype so we need to define the dependency manually 
    requires —— 由於我們在items數組中使用了一個searchfield,因此要告訴視圖require(引用)Ext.field.Search類。之所以要這樣做是因為此時的系統自動加載功能還無法通過xtype識別這個類(Twitter.view.SearchBar),所以我們不得不手動定義這個依賴項。
  • xtype - gives our new class its own xtype, allowing us to easily create it in a configuration object (just like we did with searchfield above) 
    xtype —— 給我們的新類一個自己的xtype,這樣以后就可以輕松地通過配置參數輕松的創建它了。

 
This allows us to create instances of our new view class in a couple of ways:

以后我們就可以通過兩種方式來創建新視圖(Twitter.view.SearchBar)的實例了。

//creates a standalone instance 
//
創建一個獨立的實例

Ext.create('Twitter.view.SearchBar');

 
//alternatively, use xtype to create our new class inside a Panel 
//
或者我們在一個Panel中通過xtype方式來創建它

Ext.create('Ext.Panel', {

    html: 'Welcome to my app', 

    items: [

        {

            xtype: 'searchbar',

            docked: 'top'

        }

    ]

}); 


Custom Configurations and Behavior

自定義配置和行為

Sencha Touch 2 makes extensive use of the configuration system to provide predictable APIs and keep the code clean and easily testable. We strongly suggest you do the same in your own classes.

ST2廣泛應用了configuration系統來提供可控性好的API並保持代碼簡潔和容易測試。我們強烈建議你在自己的類里面也這么做。

Let's say you want to create a image viewer that pops up information about the image when you tap on it. Our aim is to create a reusable view that can be configured with the image url, title and description, and displays the title and description when you tap on it.

假設你要創建一個圖片瀏覽視圖,當它被點擊的時候會彈出該圖片的信息。那么我們當然希望這個視圖有很好的重用性,你可以配置圖片url、標題、描述屬性,並且當點觸的時候會自動把標題和描述彈出來。

Most of the work around displaying images is taken care of for us by the Ext.Img component, so we'll subclass that:

Ext.Img組件已經圍繞圖片展示功能做了大量的工作,因此我們繼承它既可:

Ext.define('MyApp.view.Image', {

    extend: 'Ext.Img', 

    config: {

        title: null,

        description: null

    }, 

   //sets up our tap event listener

   //設置點擊事件監聽器

    initialize: function() {

        this.callParent(arguments);

        this.element.on('tap', this.onTap, this);

    }, 

   //this is called whenever you tap on the image

   //每當你點觸屏幕的時候就會調用這個函數

    onTap: function() {

        Ext.Msg.alert(this.getTitle(), this.getDescription());

    }

}); 

//creates a full screen tappable image

//創建一個全屏的可點擊的圖片

Ext.create('MyApp.view.Image', {

    title: 'Orion Nebula',

    description: 'The Orion Nebula is rather pretty', 

    src: 'http://apod.nasa.gov/apod/image/1202/oriondeep_andreo_960.jpg',

    fullscreen: true

});

 
We're adding two more configurations to our class - title and description - which both start off as null. When we create an instance of our new class we pass the title and description configs in just like any other configuration.

我們給自己的類增加了兩個新的配置參數:title和description,初始都默認為null。當我們創建這個新類的實例時,我們可以像傳遞其他參數一樣把這兩個參數傳遞進去。

Our new behavior happens in the initialize and onTap functions. The initialize function is called whenever any component is instantiated, so is a great place to set up behavior like event listeners. The first thing we do is use this.callParent(arguments) to make sure the superclass' initialize function is called. This is very important, omitting this line may cause your components not to behave correctly.

新定義的動作在初始化和點擊的時候發生,initialize函數每當組件實例化的時候都會被調用,所以這個地方用來設置事件偵聽器是最合適的。在這里我們做的第一件事是使用this.callParent(arguments)來確保父類的初始化函數已經被執行。這很重要,忽略這一步可能會導致你的組件無法正確的工作。

After callParent, we add a tap listener to the component's element, which will call our onTap function whenever the element is tapped. All components in Sencha Touch 2 have an element property that you can use in this way to listen to events on the DOM objects, add or remove styling, or do anything else you'd normally do to an Ext.dom.Element.

在callParent之后,我們給組件的element增加了一個tap偵聽器,當這個element被點擊時,onTap函數就會被調用。ST2的每一個組件都有一個element屬性,通過它你可以偵聽Dom對象的事件,增刪樣式,或者做其他你以往用Ext.dom.Element來做的事情。

The onTap function itself is pretty simple, it just uses Ext.Msg.alert to quickly pop up some information about the image. Note that our two new configs - title and description - both receivegenerated getter functions (getTitle and getDescription respectively), as well as generated setter functions (setTitle and setDescription).

onTap函數本身非常簡單,它只是使用Ext.Msg.alert來快速彈出一些關於圖片的信息。注意我們的兩個新參數title和description都自動獲得了其對應的getter方法(getTitle和getDescription),同樣還有setter方法(setTitle和setDescription)。 


Advanced Configurations

高級配置

When you create a new configuration option to a class, the getter and setter functions are generated for you so a config called 'border' is automatically given getBorder and setBorder functions:

當你為類創建一個新的配置參數時,一對getter和setter方法也會被生成,因此一個叫做border的配置參數會自動被給予getBorder和setBorder方法。

Ext.define('MyApp.view.MyView', {

    extend: 'Ext.Panel', 

    config: {

        border: 10

    }

}); 

var view = Ext.create('MyApp.view.MyView'); 

alert(view.getBorder()); //alerts 10(彈出10 

view.setBorder(15);

alert(view.getBorder()); //now alerts 15(彈出15

 
The getter and setter aren't the only functions that are generated, there are a couple more that make life as a component author much simpler - applyBorder and updateBorder:

除了getter和setter之外還會生成一對讓開發者感到很爽的方法,applyBorder和updateBorder:

Ext.define('MyApp.view.MyView', {

    extend: 'Ext.Panel', 

    config: {

        border: 0

    }, 

    applyBorder: function(value) {

        return value + "px solid red";

    }, 

    updateBorder: function(newValue, oldValue) {

        this.element.setStyle('border', newValue);

    }

});

 
Our applyBorder function is called internally any time the border configuration is set or changed, including when the component is first instantiated. This is the best place to put any code that transforms an input value. In this case we're going to take the border width passed in an return a CSS border specification string.

applyBorder函數會在每次border參數設置或者改變的時候被調用,包括組件第一次被實例化時。因此這個地方很適合放置改變參數值格式的代碼,在這個例子里我們可以把傳入的border寬度值變成css字符串格式。

This means that when we set the view's border config to 10, our applyBorder function will make sure that we transform that value to '10px solid red'. The apply function is totally optional but note that you must return a value from it or nothing will happen.

這意味着當我把視圖的border參數設為10的時候,applyBorder函數將會把這個值變成“10px solid red”這樣的字符串。apply函數你可用可不用,但是要記得在這個函數里面必須返回一個值,否則就什么效果都沒有。

The updateBorder function is called after the applyBorder function has had a chance to transform the value, and is usually used to modify the DOM, send AJAX requests or perform any other kind of processing. In our case we're just getting the view's element and updating the border style using setStyle. This means that every time setBorder is called our DOM will immediately be updated to reflect the new style.

updateBorder函數會在applyBorder已經轉換了傳入值之后被調用,通常被用來調整DOM,發送AJAX請求或者做些其他事情。這個例子中我們僅僅得到視圖的element元素並使用setStyle方法更新其border樣式,也就是說每次setBorder方法被調用后,DOM都會立即被更新成最新樣式。

Here's an example of the new view in action. Click the Code Editor button to see the source - basically we just create an instance of the new view and dock a spinner field at the top, allowing us to change the border width by tapping the spinner buttons. We hook into the Spinner's spin event and call our view's new setBorder function from there:

下面就是新視圖的示例代碼,查看源碼可知,我們創建了一個新視圖的實例並且在試圖內部放置一個緊貼頂部的spiiner,為實現點擊spinner上的增減按鈕可以改變border寬度,我們偵聽spinner的spin事件,在里面調用視圖setBorder方法。

//as before

//這里跟前面相比沒有變化

Ext.define('MyApp.view.MyView', {

    extend: 'Ext.Panel', 

    config: {

        border: 0

    }, 

    applyBorder: function(value) {

        return value + "px solid red";

    }, 

    updateBorder: function(newValue, oldValue) {

        this.element.setStyle('border', newValue);

    }

}); 

//create an instance of MyView with a spinner field that updates the border config

//創建MyView的實例,並且在其配置中使用一個spinnerfield來改變border參數

var view = Ext.create('MyApp.view.MyView', {

    border: 5,

    fullscreen: true,

    styleHtmlContent: true,

    html: 'Tap the spinner to change the border config option',

    items: {

        xtype: 'spinnerfield',

        label: 'Border size',

        docked: 'top',

        value: 5,

        minValue: 0,

        maxValue: 100,

        incrementValue: 1,

        listeners: {

            spin: function(spinner, value) {

                view.setBorder(value);

            }

        }

    }

}); 


Usage in MVC

視圖在MVC中的用法

We recommend that most Sencha Touch applications should follow the MVC conventions so that your code remains well organized and reusable. As the "V" in MVC, views also fit into this structure. The conventions around views in MVC are very simple and follow directly from the naming convention we used above.

我們強烈建議絕大多數ST應用程序都應該遵循MVC的模式開發這樣你的代碼將會組織良好並且利於重用。作為MVC中的V,視圖非常適用於這種架構。MVC中關於視圖的規則非常簡單並且跟我們上面用到的命名規則毫不沖突。

Our MyApp.view.MyView class should be defined inside a file called app/view/MyView.js - this allows the Application to find and load it automatically. If you're not already familiar with the file structure for MVC-based Sencha Touch apps, it's pretty simple - an app is just an html file, an app.js and a collection of models, views and controllers inside the app/model, app/view and app/controller directories:

我們的MyApp.view.MyView類應該在app/view/MyView.js文件中進行定義,這樣應用程序就能自動找到和加載它。如果你對“MVC式ST應用程序”的文件架構還不熟悉,你可以這么理解:一個應用程序就是一個html、一個app.js、再加上分處於app/model、app/view、app/controller目錄下的一堆model、view、controller文件的集合:

index.html

app.js

app/

    controller/

    model/

    view/

        MyView.js

 
You can create as many views as you want and organize them inside your app/view directory. By specifying your application's views inside your app.js they'll be loaded automatically:

你可以按照你的需要創建很多視圖文件放在app/view目錄里。通過在app.js中指定application的views參數,他們就能被自動加載了。

//contents of app.js

//app.js內容

Ext.application({

    name: 'MyApp',

    views: ['MyView'], 

    launch: function() {

        Ext.create('MyApp.view.MyView');

    }

});

 
By following the simple view naming conventions we can easily load and create instances of our view classes inside our application. The example above does exactly that - loads the MyView class and creates an instance of it in the application launch function. To find out more about writing MVC apps in Sencha Touch please see the intro to apps guide.

遵循這種簡單的視圖命名規則,我們可以在應用程序中很輕易的加載視圖類並創建其實例。上述的例子就是這樣做的:載入了MyView類然后在application的launch函數里創建了該類的實例。想要了解更多關於MVC式ST應用程序的編寫方法,請跳轉至《應用程序開發指南》頁面(譯者注:也就是此翻譯系列的第一篇:Intro to Applications with Sencha Touch 2)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM