원본글 :  Views

번역자 : 박정환 <dynamiczoe@gmail.com>

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:

결과는 같지만, 이번에는 새로운 부품을 이용해서  몇번에 걸쳐 만들어 보겠습니다. 이것은 우리가 일반적으로 앱을 만들때 따르는 패턴입니다.

  • We used Ext.define for creating a new class, by extending an existing one (Ext.Panel in this case)
  • 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
  • We defined config for the new class inside a config object
  • Ext.define를 새로운 클래스 생성에 사용하고, 이것은 존재하는 클래스의 확장으로 인해 생성합니다. (이번엔Ext.Panel사용됨)
  • 새로운 보기 클래스는 MyApp.view.MyView관습을 따릅니다. 당신이 짓고싶은 어떤 이름을 지어도 상관없지만, 명명 관습에 따르기를 권고하고 있습니다.
  • 새로운 클래스의 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:

다음 예제는 트위터 앱의 한가지 보기 클래스를 보여줍니다:

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
  • 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
  • 요구들 – 아이템 배열에서 검색필드를 사용했기때문에, Ext.field.Search클래스에서 새로운 보기를 가리키길 요구합니다. 그순간 동적 로딩 시스템에서는 xtype로 클래스를 인식하지 못합니다. 그래서 우리는 수동으로 의존성을 정의할 필요가 있습니다.
  • xtype – 새로운 클래스들에 각자의 xtype들을 제공합니다. 이것은 우리에게 설정객체를 더 쉽게 만들도록 해주고, 검색필드와의 호환도 좋습니다.

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.

센차터치는 광범위한 환경설정 시스템으로 예측되는 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.

당신이 이미지를 클릭하면 그 위에 정보를 나타내어 주는 이미지뷰어를 만들고 싶다고 가정하면. 우리의 디자인 목표는 그림을 클릭하면 그위에 이미지의 주소, 제목, 설명을 나타내어 주는 재사용 가능한 보기를 만드는 것입니다.

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 component로 인해 우리에게 관리되고, 그래서 다음과 같이 하위 클래스를 만들었습니다:

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.

이번 예제에서 우리는 off와 null값으로 시작되는 두개의 부가적인 환경설정을 클래스에 추가했습니다.(제목과 설명) 우리가 클래스의 인스턴스를 생성할때, 우리는제목과 설명 설정을 다른설정과 같이 지나쳤습니다.

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.

새로운 행동이 초기화와 클릭하는 기능에서 일어났습니다. 기능 초기화가 되기까지 어떤 부품이든 언제든지 호출될 수 있습니다. 이것은 이벤트 리스너같은 행동을 설치하기 좋은 위치 입니다.

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 함수를 호출합니다. 모든 센차터치의 부품들은 부분 속성을 가지고 있습니다. 이것은 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로 사용하고, 해당 이미지에 대한 정보를 출력합니다. 우리의 새로운 두개의 환경설정(제목과 설명)에 주목하면, 두가지 모두 생성된 getter함수(getTitle과 getDescriprion)와 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함수는 당신을 위해 생성됩니다. 예를들어 다음과 같이 config가’border’를 호출하면 자동적으로 getBoder와 setBoder함수가 주어집니다.

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는 생성되기만 하는 함수는 아닙니다. 생명 주기를 불어넣을 만한 몇가지가 더 있습니다.

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.

applyBoder 함수는 boder 환경설정이 초기화될때를 포함하여 설정되거나 바뀔때는 언제든 내부적으로 호출됩니다. 이것은 입력값을 변환하는코드를 넣는 데 가장 좋은 위치입니다. 이런경우 우리는 boder의 굵기값을 지나치고 CSS boder 제원 문자열을 반환합니다.

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.

이것은 보기의 boder값을 10으로 설정할때 applyBoder함수는 ’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.

updateBoder 함수는 applyBoder 함수가 값을 변경한 다음에 호출됩니다. 그리고 이것은 DOM을 수정할때, AJAX요청을 보낼때나 다른 많은 종류의 작업을 할때 자주 사용됩니다. 이번 경우에 우리는 보기의 요소를 받고, setStyle로 boder스타일을 업데이트했습니다. 이것은 setBoder를 호출할때 매번 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:

다음의 코드는 보기의 활동에대한 예제입니다. 기본적으로 우리는 새로운 보기의 인스턴스를 생성하였고, 회전영역을 상단에 위치 시켜서, boder굵기를 회전버튼으로 바꿀 수 있게 하였습니다. 회전버튼의 회전 이벤트와 보기의 setBoder함수를 연결시켰습니다:

 
//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.

우리는 대부분의 센차터치 애플리케이션이 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기반의 센차터치앱들을 위한 파일구조와 익숙해지지 않았다면 이것은 쉬울것입니다. – 앱은 html파일이고 app.js파일이거나, 모델의 집합이거나,app/modelapp/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 directory 안에 만들고자 하는 갯수만큼 보기들을 만들 수 있습니다. 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.

보기 명명관례들을 따라하다 보면, 당신의 어플리케이션의 보기 클래스들의 인스턴스를 쉽게 불러오고 만들 수 있습니다. 이전의 예제들은 어플리케이션의 실행함수가 실행되면  MyView클래스를 불러오고 그 인스턴스를 만듭니다. 센차터치에서 더 많은 MVC기능들을 사용하려면 intro to apps guide 를 참고해 주세요