第十一天(Using Views in Your Applications)

原文地址:http://docs-origin.sencha.com/touch/2.2.0/#!/guide/views

Using Views in Your Applications

在你的应用中使用视图

From a user's point of view, your application is simply a collection of views. Although much of the value of the app is in the Models and Controllers, users directly interact with the Views. In this guide we are 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 use Ext.create with an existing Component. For example, if we wanted to create a simple Panel with some HTML inside, we can use the following code:

最简单的创建视图的方法是用Ext.create创建已经存在的组件的视图。例如,如果我们想创建内部有一些html内容的面板,我们可以使用下面的代码:

Ext.create('Ext.Panel', {
    html: 'Welcome to my app',
    fullscreen: true
});

This example creates a Panel with some html content and makes it fill the screen. Although you can create any of the built-in components this way, the best practice is to create a subclass with your specializations and then instantiate that class as follows:

这个例子创建了一个有一些html内容的面板,并使之沾满屏幕。尽管你可以以这种方式创建任何内部组件,最好的方式是创建一个专门的子类,然后实例化它,如下所示:

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 this time we have a new component that we can create any number of times. This is the pattern we normally want to follow when building our app - create a subclass of an existing component, then create an instance of it later. Let us take a look at the changes:

结果是一样的,但是这一次我们有一个新的组件,我们可以多次创建该组件。这是我们创建app时想要遵从的方式——创建已存在组件的子类,稍后再实例化它。下面看下这种方式的不同点:

  • We used Ext.define for creating a new class, by 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. Although you can name it whatever you like, we suggest sticking with this naming convention    我们的新类遵从了MyApp.view.MyView的命名规范。尽管你可以给它任何名字,我们推荐使用该命名规范
  • We defined config for the new class inside a config object          我们通过config对象来定义config配置

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

Ext.Panel中任何可用的config配置都可以在新类的config块中配置,或者当我们实例化的时候配置。当定义一个子类时,要确保使用config对象,当创建的时候传递一个对象即可。

For example, the following code is based on the previous code, but with additional configuration passed in with the 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

一个真实的例子

The following exmple illustrates 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 code sample follows the same pattern as before - we created a new class called Twitter.view.SearchBar, which extends the framework's Ext.Toolbarclass. We also passed in some configuration options, including a layout and an items array.

上面的代码遵从了同前面一样的命名规范——我们创建了一个叫Twitter.view.SearchBar的类,该类继承自框架中的Ext.Toolbar。我们也传入了一些配置功能,包括布局及一个数组形式的子项。

In this example we used the following new options:

在这个例子中我们用到了如下新的功能:

  • requires - because we use a searchfield in our items array, we indicate the 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——因为我们在item子项中用到了searchfield,我们指定新类需要Ext.field.Search这个类。此时,动态加载系统不能根据xtype识别类,因此我们需要手动的定义依赖。
  • xtype - gives our new class its own xtype, allowing us to easily create it in a configuration object, which is similar to the approach taken with the searchfield      xtype——给我们自己的类一个xtype,这样,我们可以通过configuration对象很容易的创建它,就跟searchfield的创建方式一样。

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

这使得我们能够以多种方式创建新视图的实例:

//creates a standalone instance
Ext.create('Twitter.view.SearchBar');

//alternatively, use xtype to create our new class inside a Panel
Ext.create('Ext.Panel', {
    html: 'Welcome to my app',

    items: [
        {
            xtype: 'searchbar',
            docked: 'top'
        }
    ]
});

Custom Configurations and Behavior

自定义配置及行为

Sencha Touch 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.

st对配置系统做了广阔的使用,以提供可预知的api及保持代码的整洁性和可测试性。我们强烈建议你在自己的类中也这样使用。

Let us assume that you want to create an image viewer that pops up information about the image when you tap on it. Our design goal is to create a reusable view that can be configured with the image url, its title and its description, and that 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 subclass that as follows:

我们所关心的展示图片的很多工作已经被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 function 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
});

In this example, we have added two additional configurations to our class - title and description - which both start off as null. When we create an instance of our new class, we pass in the title and the description configs like any other configuration.

在这个例子中,我们添加了两个额外的配置项——title和description,这两个的初始值均为null。当我们创建新类的实例时,我们像其它配置项样传入title和description参数。

The new behavior occurs in the initialize and onTap functions. Since the initialize function is called whenever any component is instantiated, it is a good place to set up behavior such as event listeners. First we 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和onTap方法中。因为initialize方法是在组件实例化的时候调用,因此这里是设置行为如事件监听器的一个很好的地方。首先,我们用this.callParent(arguments)方法确保父类的initialize方法被调用。这是非常重要的,省略这一行可能导致你的组件不能正常工作。

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

在调用callParent后,我们向组件的元素添加了一个点击监听器,该监听器会在元素被点击时触发onTap方法。st中的所有组件均有一个element属性,你可以像上面的方式那样在dom对象中监听事件、添加、移除样式或者其它 你想对Ext.dom.Element做的任何操作。

The onTap function itself uses Ext.Msg.alert to pop up some information about the image. Note that our two new configs - title and description - both receive generated 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. For example, the config called 'border' in the following example 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

view.setBorder(15);
alert(view.getBorder()); //now alerts 15

The getter and setter are not the only generated functions, 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);
    }
});

The 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 take the border width passed in and return a CSS border specification string.

applyBorder方法会在border配置被设置或修改时由系统内部调用,包括组件第一次被实例化。这里是放置转换输入值的最好位置。这个例子中,我们用传入的border值返回了一个css border的字符串。

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 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 transformed the value, and is usually used to modify the DOM, to send AJAX requests, or to perform any other kind of processing. In our case we are getting the view's element and updating the border style using setStyle. This means that every time setBorder is called, the DOM is immediately updated to reflect the new style.

updateBorder方法在applyBorder方法转换值之后,该方法通常是用来修改dom、发送ajax请求或进行其他类型的处理。在我们的例子中,我们是获得视图的元素并用setStyle方法更新border样式。这意味着每当setBorder被调用,dom都会应用最新的样式。

The following code is an example of the new view in action. Click the Code Editor button to see the source - basically we created an instance of the new view and docked a spinner field at the top, allowing us to change the border width by tapping the spinner buttons. We then hooked into the Spinner's spinevent and called our view's new setBorder function from there:

下面的代码是可运行的最新的视图。单击Code Editor按钮查看源代码——总的来说,我们创建该视图的一个实例,将spinner控件置于顶部,通过点击spinner按钮允许我们改变border的宽度。然后我们在Spinner的spinevent事件中调用视图的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
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,
        increment: 1,
        listeners: {
            spin: function(spinner, value) {
                view.setBorder(value);
            }
        }
    }
});
 

Usage in MVC

在mvc中的使用

We recommend that most Sencha Touch applications 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 throughout the previous examples.

我们推荐st应用程序遵从MVC规范,这样你的代码能够保持良好的组织性和可重用性。就像MVC中的V样,视图也与该结构融为一体。MVC中关于视图的规范很简单,仅仅是遵从命名规范就像上一个例子所示。

The 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 are not already familiar with the file structure for MVC-based Sencha Touch apps, it is pretty simple - an app is just an html file, an app.js file, and a collection of models, views and controllers stored inside the app/modelapp/view and app/controller directories:

MyApp.view.MyView类应该定义在app/view/MyView.js文件中——这允许应用程序查找和自动加载它。如果你对基于MVC的st应用结构不熟,它是相当的简单——一个app是包含一个app.js文件,及位于app/model下的一些列模型、位于app/view下的视图、位于app/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 file, they are loaded automatically:

你可以根据需要创建任意数量的视图,并将它们在app/view目录下进行组织。通过在app.js文件中指定你的视图,它们会被自动加载:

//contents of app.js
Ext.application({
    name: 'MyApp',
    views: ['MyView'],

    launch: function() {
        Ext.create('MyApp.view.MyView');
    }
});

By following the simple View naming conventions, you can easily load and create instances of View classes inside your application. The previous example does exactly that - it 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.

通过遵从视图的命名规范,你可以很容易的在应用中加载、创建视图的实例。上面的例子就是如此——在application的launch方法中加载了MyView类并创建爱你了它的实例。可以查看 intro to apps guide获取更多关于创建一个MVC 模型的st应用。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值