翻译

Sencha学习笔记4: Creating your First App - 官方创建您的第一个Sencha Touch应用指导

英文原文地址http://docs.sencha.com/touch/2.3.1/#!/guide/first_app (天地会珠海分舵声明:本翻译文章建议读者参照英文原文进行阅读,因为原文包含了实时代码编辑和预览的功能,这在csdn是不能做到的,所以下面只是提供了相应的截图,而非真实的演示)

Required Software 

软件需求

Create a Starting Environment 

环境准备

请参考《Sencha学习笔记1: Getting Started with Sencha Touch - 官方Sencha Touch入门指南


What We Are Creating  

我们究竟在创建什么东东

We are creating a simple mobile web app to use for a company's mobile site. The app includes a home page, a contact form, and a simple list that fetches Sencha's recent blog posts and allows visitors to read them on a mobile device.

我们将要创建的是一个简单的公司移动网站网络应用。该应用包含一个主页,一个联系人表单,以及一个简单的用来获取Sencha最近更新的博客文章的列表 - 访客可以通过移动设备来阅读浏览该博客信息。

After you have unzipped Sencha Touch, you can replace the code in the app.js file with the example that follows.

当你把Sencha Touch解包之后,你就可以用下面的示例代码来覆盖app.js文件中的相应部分代码。

Note: The starting content in the app.js file contains extra code you can ignore for this example.

注意:在本向导示例中读者可以忽略掉app.js文件中前面部分的额外的代码内容。

The following is an interactive sample app that you can change the code and preview the results:

以下是一个网页模拟的交互应用示例,你可以改变代码的内容然后点击"预览(Live Preview)"按钮来查看结构(天地会珠海分舵:这一部分建议大家在原文中进行修改然后查看预览结果,在csdn中无法模拟,但下面会贴出对应的代码和预览图示例):


天地会珠海分舵:通过点击左上角的Code Editor(代码编辑)我们可以看到对应的示例代码,并且可以修改该代码,然后点击Live Preview(预览)来查看修改后的变化。下面我们看下上图对应的示例代码

Ext.application({
    name: 'Sencha',

    launch: function() {

        Ext.create('Ext.data.TreeStore', {
            storeId: 'TreeStore',
            fields: ['title', 'link', 'author', 'contentSnippet', 'content', {
                name: 'leaf',
                defaultValue: true
            }],
            root: {
                leaf: false
            },
            proxy: {
                type: 'jsonp',
                url: 'https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=http://feeds.feedburner.com/SenchaBlog',
                reader: {
                    type: 'json',
                    rootProperty: 'responseData.feed.entries'
                }
            }
        });        
        Ext.create("Ext.tab.Panel", {
            fullscreen: true,
            tabBarPosition: 'bottom',

            items: [
                {
                    title: 'Home',
                    iconCls: 'home',
                    cls: 'home',
                    html: [
                        '<img width="65%" src="http://staging.sencha.com/img/sencha.png" />',
                        '<h1>Welcome to Sencha Touch</h1>',
                        "<p>We're creating the Getting Started app, which demonstrates how ",
                        "to use tabs, lists, and forms to create a simple app.</p>",
                        '<h2>Sencha Touch</h2>'
                    ].join("")
                },
                {
                    xtype: 'nestedlist',
                    title: 'Blog',
                    iconCls: 'star',
                    displayField: 'title',

                    store: 'TreeStore',

                    detailCard: {
                        xtype: 'panel',
                        scrollable: true,
                        styleHtmlContent: true
                    },

                    listeners: {
                        itemtap: function(nestedList, list, index, element, post) {
                            this.getDetailCard().setHtml(post.get('content'));
                        }
                    }
                },
                // this is the new item
                {
                    title: 'Contact',
                    iconCls: 'user',
                    xtype: 'formpanel',
                    url: 'contact.php',
                    layout: 'vbox',

                    items: [
                        {
                            xtype: 'fieldset',
                            title: 'Contact Us',
                            instructions: '(email address is optional)',
                            height: 285,
                            items: [
                                {
                                    xtype: 'textfield',
                                    label: 'Name'
                                },
                                {
                                    xtype: 'emailfield',
                                    label: 'Email'
                                },
                                {
                                    xtype: 'textareafield',
                                    label: 'Message'
                                }
                            ]
                        },
                        {
                            xtype: 'button',
                            text: 'Send',
                            ui: 'confirm',
                            handler: function() {
                                this.up('formpanel').submit();
                            }
                        }
                    ]
                }
            ]
        });
    }
});

Getting Started 

预备...跑!

Because the app uses a tab panel that holds the four pages, we start by creating the UI. The entry point for Sencha Touch is the launch function of an Ext.application. Consider this the main part of the application, and the place that contains the application logic.

该应用使用的是一个标签面板来把四个页面放在上面的,所以我们就先从创建这些界面开始吧。Sencha Touch应用的入口是一个Ext.application的launch函数。可以把这认为是应用的主入口位置,以及包含应用运行逻辑的的地方。


对应的app.js代码如下所示:

Ext.application({
    name: 'Sencha',

    launch: function() {
        Ext.create("Ext.tab.Panel", {
            fullscreen: true,
            items: [
                {
                    title: 'Home',
                    iconCls: 'home',
                    html: 'Welcome'
                }
            ]
        });
    }
});

If you run this code in the browser (by clicking the Preview button), a TabPanel appears on top of the screen. Since the home page could be a bit more welcoming, add some content to it and reposition the tab bar at the bottom of the page. By default, the tab bar is positioned at the top of the page, but setting the tabBarPosition config moves it to the page bottom. Then we add HTML into the items array to create content. Use items arrays to add child items into a container, as shown in the following code:

如果你在浏览器上运行以上代码(通过点击预览/Preview按钮),一个标签面板就会在屏幕的左上角出现。为了让主页面可以变得更宜人,我们可以在上面加些内容并且把标签栏放到屏幕下方部位。默认的话,标签栏是显示在屏幕的上方的,但我们可以设置标签面板的tabBarPosition属性来把它移动到屏幕下方。然后我们增加相应的HTML内容/item到items数组里面来创建相应的内容。通过在items数组中增加子项到容器里面,如以下代码所示:

Ext.application({
    name: 'Sencha',

    launch: function() {
        Ext.create("Ext.tab.Panel", {
            fullscreen: true,
            tabBarPosition: 'bottom',

            items: [
                {
                    title: 'Home',
                    iconCls: 'home',
                    html: [
                        '<img src="http://staging.sencha.com/img/sencha.png" />',
                        '<h1>Welcome to Sencha Touch</h1>',
                        "<p>We're creating the Getting Started app, which demonstrates how ",
                        "to use tabs, lists, and forms to create a simple app.</p>",
                        '<h2>Sencha Touch</h2>'
                    ].join("")
                }
            ]
        });
    }
});

You can click the Preview button next to the example to inspect the result: you should see some HTML content, but it will not look very good. 

你可以点击上面的预览(Preview)按钮来检验结果:你可以看到在主界面上显示的相应的html的内容,但是看起来并不是很好看。


We add a cls config to the panel, adding a CSS class that we can target to make things look better. The CSS we add is in the examples/getting_started/resources/css/app.css file in the SDK download. Here is how the home page looks at this point:

我们可以为该面板增加一个cls配置,通过增加一个CSS类来让界面显示的更友好。我们需要增加的CSS放在你所下载的SDK里面的examples/getting_started/resources/css/app.css文件里面。以下展示了主界面使用了CSS样式后的效果:


对应的代码:

Ext.application({
    name: 'Sencha',

    launch: function() {
        Ext.create("Ext.tab.Panel", {
            fullscreen: true,
            tabBarPosition: 'bottom',

            items: [
                {
                    title: 'Home',
                    iconCls: 'home',
                    cls: 'home',

                    html: [
                        '<img src="http://staging.sencha.com/img/sencha.png" />',
                        '<h1>Welcome to Sencha Touch</h1>',
                        "<p>We're creating the Getting Started app, which demonstrates how ",
                        "to use tabs, lists, and forms to create a simple app.</p>",
                        '<h2>Sencha Touch</h2>'
                    ].join("")
                }
            ]
        });
    }
});

CSS样式:

.home{text-align:center}.home h1{font-weight:bold;font-size:1.2em}.home p{color:#666;font-size:0.8em;line-height:1.6em;margin:10px 20px 20px 20px}.home img{margin-top:-10px}.home h2{color:#999;font-size:0.7em}.blog p{color:#555;padding:20px 20px 0 20px;font-size:1em;line-height:1.4em}

Adding the Blogs Page 

增加博客页面

Now that we have a decent looking home page, we move to the next screen. To keep the code for each page easy to follow, we create one tab at a time and then combine them all together at the end.

现在我们已经拥有了一个漂亮的主界面了,是时候转到下一个屏幕了。为了让每个页面的代码更容易阅读和理解,我们每次会创建一个标签页(的代码),并会在最后把这些页面的代码放在一起。

For now, we remove the first tab and replace it with a List. We use Google's Feed API service to fetch the feeds. Because there is more code involved, first we take a look at the result, then we explain how we accomplish it:

现在就让我们移除掉前面第一个标签页的代码并用一个List列表来取代它。我们将使用的是Google的Feed API service来获取博客动态信息。因为这将会涉及不少的代码,所以我们下面首先去看下最终效果,然后我们会对如何实现该效果进行解析:


You can click the 'Code Editor' button above the example code to see the full code, but we will go over it piece by piece. 

你可以点击上方的’代码编辑‘('Code Editor‘)按钮来查阅完整的代码,但此后我们会一点点的走阅该代码。

Ext.application({
    name: 'Sencha',

    launch: function() {
        Ext.create("Ext.tab.Panel", {
            fullscreen: true,
            tabBarPosition: 'bottom',

            items: [
                {
                    xtype: 'nestedlist',
                    title: 'Blog',
                    iconCls: 'star',
                    displayField: 'title',

                    store: {
                        type: 'tree',

                        fields: [
                            'title', 'link', 'author', 'contentSnippet', 'content',
                            {name: 'leaf', defaultValue: true}
                        ],

                        root: {
                            leaf: false
                        },

                        proxy: {
                            type: 'jsonp',
                            url: 'https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=http://feeds.feedburner.com/SenchaBlog',
                            reader: {
                                type: 'json',
                                rootProperty: 'responseData.feed.entries'
                            }
                        }
                    },

                    detailCard: {
                        xtype: 'panel',
                        scrollable: true,
                        styleHtmlContent: true
                    },

                    listeners: {
                        itemtap: function(nestedList, list, index, element, post) {
                            this.getDetailCard().setHtml(post.get('content'));
                        }
                    }
                }
            ]
        });
    }
});

At this point, instead of a panel, we use a nestedlist, and populate the list with the most recent blog posts fetched from sencha.com/blog. We use a Nested List component so that we can drill down in the blog entry by tapping the list.

在这种情况下,我们使用的将不是面板,而是一个nestedlist控件,并且产生一个包含从sencha.com/blog获取的最新博客动态信息的列表。因为我们使用的是Nested List组件,所以我们可以通过点击一个博客条目来打开该博客的深层信息。


Let us break down the previous code, starting with the list itself:

下面让我们对前面的代码进行分解,我们先从该列表自身开始:

Ext.application({
    name: 'Sencha',

    launch: function() {
        Ext.create("Ext.tab.Panel", {
            fullscreen: true,
            tabBarPosition: 'bottom',

            items: [
                {
                    xtype: 'nestedlist',
                    title: 'Blog',
                    iconCls: 'star',
                    displayField: 'title',

                    store: {
                        type: 'tree',

                        fields: [
                            'title', 'link', 'author', 'contentSnippet', 'content',
                            {name: 'leaf', defaultValue: true}
                        ],

                        root: {
                            leaf: false
                        },

                        proxy: {
                            type: 'jsonp',
                            url: 'https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=http://feeds.feedburner.com/SenchaBlog',
                            reader: {
                                type: 'json',
                                rootProperty: 'responseData.feed.entries'
                            }
                        }
                    }
                }
            ]
        });
    }
});


In the previous code, we gave the Nested List a number of one-line configurations - title, iconCls, and displayField - and a more detailed one called store. The Store config tells the nested list how to fetch its data. Let's examine each Store configuration:

在上面的代码中,我们通过一行一个配置来赋予了Nested List控件若干个配置 - title(标题),iconCls(图标类型),以及diaplayField(显示字段) - 甚至一个包含更多详细信息的store配置项。该Store配置项将会告诉Nested List控件应该如何去获取数据。下面让我们看下Store的各项配置信息:

  • type: tree - Creates a tree store, which NestedList uses.
  • type: tree - 创建一个给NestedList控件使用的tree store
  • fields - Tells the Store what fields we expect in the blog data (title, content, author, and so on).
  • fields - 告诉Store我们想要的是博客数据中的哪些字段(标题,内容,作者,以及其他)。
  • proxy - Tells the Store from where to fetch its data.
  • proxy - 指示Store应该去哪里获取数据
  • root - Tells the root node it is not a leaf. Since earlier in the code, we set the leaf defaultValue to true, we need to override that for the root.
  • root - 标明一个根节点不应该是一个叶节点。因为在前面的代码中,我们把叶节点的的defaultValue设置成true了,我们应该为根节点重写该值。

Of all the Store configurations, proxy is doing the most important work. We are telling the proxy to use Google's Feed API service to return our blog data in JSON-P format. This allows us to grab feed data from a blog and view it in our app (for example try swapping the Sencha blog URL for http://rss.slashdot.org/Slashdot/slashdot in the previous example to fetch Slashdot's feed).

在所有的Store配置项中,proxy是处于最重要的位置的。我们告诉proxy去使用Goole的Feed API service来以JSON-P格式来返回我们的博客数据。这就允许我们抓取到从博客回馈过来的数据并在我们的应用中把它显示出来(比如你也可以把上面代码的Sencha博客的URL给替换成http://rss.slashdot.org/Slashdot/slashdot来获取Slashdot的回馈数据)

The last part of the proxy definition is a Reader. The reader is the entity that decodes the response from Google into useful data. When Google sends back the blog data, they nest it inside a JSON object that looks a bit like in the following example:

proxy定义的最后一个配置选项是Reader。Reader是用来对Google返回的数据解码成有用数据的一个实体。当Google发回来对应的博客数据的时候,它会把这些数据嵌套在一个JSON对象里面,这看起来会有点像下面的示例:

{
    responseData: {
        feed: {
            entries: [
                {author: 'Bob', title: 'Great Post', content: 'Really good content...'}
            ]
        }
    }
}

In this code, the important part is the entries array, so we set our Reader's rootProperty to 'responseData.feed.entries' and let the framework do the rest.

在这段代码里面,关键部分是entries这个数组,所以我们把Reader的rootProperty设置成"responseData.feed.entries',然后让框架去处理剩下的事情。

Digging In 

继续往下挖

Now that we have our nested list fetching and showing data, we need to allow users to tap an entry to read it. To add this functionality, we add two more configurations to our Nested List, as follows:

现在我们的Nested List控件已经可以获取和显示数据了,下一步我们就需要让用户来触点其中一个条目来读取该博客的详细信息了。为了增加这些功能,我们需要增加额外的两个配置项到Nested List里面,如下所示:

{
    xtype: 'nestedlist',
    //all other configurations as above

    detailCard: {
        xtype: 'panel',
        scrollable: true,
        styleHtmlContent: true
    },

    listeners: {
        itemtap: function(nestedList, list, index, element, post) {
            this.getDetailCard().setHtml(post.get('content'));
        }
    }
}

In this code sample, we create a detailCard, which is a useful feature of Nested List that allows you to show a different view when a user taps on an item. We configured our detailCard to be a scrollable Panel that uses styleHtmlContent to make the text look good.

在这个代码示例当中,我们创建了一个detailCard的配置项,该配置项是Nested List控件一个非常有用的功能,它将允许你在触点Nested List下面的一个条目的时候弹出另外一个窗口。这里我们把detailCard配置成可滚动的面板,并且通过指定styleHtmlContent配置选项来让文本显示的更好看点。

The final step is adding an itemtap listener, which calls our function whenever an item is tapped on. The function sets the detailCard's HTML to the content of the post on which you tapped. The framework animates the detail card into view to make the post appear. This was the only line of code we had to write to make the blog reader work.

最后一个步骤就是增加一个叫做itemtap的监听者,每当一个条目被触点的时候都会触发我们这里的方法。该方法做的事情就是把detailCard的HTML属性设置成你触点的条目所post(提交)的内容。框架本身会把该detail card构造成一个窗口来让post数据显示在上面。这就是我们为了让读取博客的功能工作起来所需要编写的唯一一行代码。

Creating a Contact Form 

创建一个联系人表单

The final thing we do for our app is create a contact form. We take the user's name, email address, and a message, and use a FieldSet to make it look good. The code for this functionality is as follows:

构建这个app需要做的最后一个事情就是去创建一个联系人表单。我们将需要显示的是用户名,邮箱地址,以及一个消息内容,并且这里采用了一个FieldSet 的项来让这些信息更好的显示出来。本功能的相关代码如下所示:
Ext.application({
    name: 'Sencha',

    launch: function() {
        Ext.create("Ext.tab.Panel", {
            fullscreen: true,
            tabBarPosition: 'bottom',

            items: [
                {
                    title: 'Contact',
                    iconCls: 'user',
                    xtype: 'formpanel',
                    url: 'contact.php',
                    layout: 'vbox',

                    items: [
                        {
                            xtype: 'fieldset',
                            title: 'Contact Us',
                            instructions: '(email address is optional)',
                            height: 285,
                            items: [
                                {
                                    xtype: 'textfield',
                                    label: 'Name'
                                },
                                {
                                    xtype: 'emailfield',
                                    label: 'Email'
                                },
                                {
                                    xtype: 'textareafield',
                                    label: 'Message'
                                }
                            ]
                        },
                        {
                            xtype: 'button',
                            text: 'Send',
                            ui: 'confirm',
                            handler: function() {
                                this.up('formpanel').submit();
                            }
                        }
                    ]
                }
            ]
        });
    }
});
对应的效果如下图所示:

This time we create a form that contains a fieldset. The fieldset contains three fields - one for a name, one for email address, and one for a message. We use a VBox layout to arrange the items vertically on the page, one above the other.

这一次我们创建了一个包含fieldsetform。其中fieldset包含了三个字段 - 其一是名称,其二是邮件地址,其三是一个消息。这里我们使用的是VBox layout的布局方式来把这些元素垂直显示出来,且这三个的位置上下连续的。

At the bottom of the panel we added a Button with a tap handler. The handler uses the up method, which returns the form panel containing the button. We then call submit to submit the form, which sends it to the specified URL ('contact.php').

在面板下面我们增加了一个按钮,并且为该按钮增加了一个触点处理函数句柄。该句柄使用up方法来获取到参数指定的含有该按钮的表单面板容器父控件"formpanel",然后调用submit方法来提交该表单,也就是把该表单信息发送到指定的URL ('contact.php')来进行处理了。

Putting It All Together 

整合所有页面

After creating each view individually, let's bring them all together into a complete app:

在创建好上面几个各自独立的View后,我们就可以开始把他们整合在一起来形成一个完整的应用:


对应代码:

// We've added a third and final item to our tab panel - scroll down to see it
Ext.application({
    name: 'Sencha',

    launch: function() {

        Ext.create('Ext.data.TreeStore', {
            storeId: 'TreeStore',
            fields: ['title', 'link', 'author', 'contentSnippet', 'content', {
                name: 'leaf',
                defaultValue: true
            }],
            root: {
                leaf: false
            },
            proxy: {
                type: 'jsonp',
                url: 'https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=http://feeds.feedburner.com/SenchaBlog',
                reader: {
                    type: 'json',
                    rootProperty: 'responseData.feed.entries'
                }
            }
        });        
        Ext.create("Ext.tab.Panel", {
            fullscreen: true,
            tabBarPosition: 'bottom',

            items: [
                {
                    title: 'Home',
                    iconCls: 'home',
                    cls: 'home',
                    html: [
                        '<img width="65%" src="http://staging.sencha.com/img/sencha.png" />',
                        '<h1>Welcome to Sencha Touch</h1>',
                        "<p>We're creating the Getting Started app, which demonstrates how ",
                        "to use tabs, lists, and forms to create a simple app.</p>",
                        '<h2>Sencha Touch</h2>'
                    ].join("")
                },
                {
                    xtype: 'nestedlist',
                    title: 'Blog',
                    iconCls: 'star',
                    displayField: 'title',

                    store: 'TreeStore',

                    detailCard: {
                        xtype: 'panel',
                        scrollable: true,
                        styleHtmlContent: true
                    },

                    listeners: {
                        itemtap: function(nestedList, list, index, element, post) {
                            this.getDetailCard().setHtml(post.get('content'));
                        }
                    }
                },
                // this is the new item
                {
                    title: 'Contact',
                    iconCls: 'user',
                    xtype: 'formpanel',
                    url: 'contact.php',
                    layout: 'vbox',

                    items: [
                        {
                            xtype: 'fieldset',
                            title: 'Contact Us',
                            instructions: '(email address is optional)',
                            height: 285,
                            items: [
                                {
                                    xtype: 'textfield',
                                    label: 'Name'
                                },
                                {
                                    xtype: 'emailfield',
                                    label: 'Email'
                                },
                                {
                                    xtype: 'textareafield',
                                    label: 'Message'
                                }
                            ]
                        },
                        {
                            xtype: 'button',
                            text: 'Send',
                            ui: 'confirm',
                            handler: function() {
                                this.up('formpanel').submit();
                            }
                        }
                    ]
                }
            ]
        });
    }
});

Next 

下一步

You can find the full source code of the Getting Started app in Sencha Fiddle.

你可以从Sencha Fiddle中找到完整的示例源码。

After you create your app, you can build it using this command:

在创建好你的应用后,你可以通过下面的命令来进行构建:

sencha app build

For more information on building your app, see Using and Creating Builds and Introduction to Sencha Cmd.

关于更多的如何构建你的应用的信息,请查看Sencha Cmd中的使用及构建以及引言章节。



作者

自主博客

微信

CSDN

天地会珠海分舵

http://techgogogo.com


服务号:TechGoGoGo

扫描码:

http://blog.csdn.net/zhubaitian


文章最后发布于: 2015-01-28 10:12:51
展开阅读全文
0 个人打赏
私信求帮助

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览