如何创建一个Sencha Touch 2应用_记事本案例(第五部分)

    

Many of the readers of this tutorial on how to build a Sencha Touch Application have requested a version of the Notes Application that shows how to create components using the config object, instead of the initialize function. In this chapter of the tutorial, we are going to do just that.


很多此系列教程的读者都在要求一个使用config创建视图控件的版本,而不是我们在前几节使用的在initailize()函数中添加控件。所以在这一章我们只是修改我们的应用,使用config来创建控件,仅此而已。


Using Sencha Touchs Config Object to Create the Notes List(使用STconfig对象创建list


The first step we are going to take is consolidate the Notes List Container View and Notes List View into a single View, which we will call Notes List View. This View has the same components that used to exist in the former Views:

第一步我们把NoteListContainer类和NotesList类合并为一个类:NotesList。这个视图包含的控件和前面的版本一样:

如何创建一个Sencha Touch 2应用_记事本案例(第五部分)_第1张图片


In the applications view directory, we are going to delete the old NotesListContainer.js file, and leave only the NotesList.js and NoteEditor.js files:

修改之后的view目录是这样的:



Next, we are going to remove the existing code from the NotesList.js file, and define the NotesList class like so:

接下来我们这样定义NotesList类:


Ext.define("NotesApp.view.NotesList", {
    extend: "Ext.Container",
    requires:"Ext.dataview.List",
    alias: "widget.noteslistview",
    config: {
        layout: {
            type: 'fit'
        },
        items: [{
            xtype: "toolbar",
            title: "My Notes",
            docked: "top",
            items: [
                { xtype: 'spacer' },
                {
                    xtype: "button",
                    text: 'New',
                    ui: 'action',
                    itemId: "newButton"
                }
            ]
        }, {
            xtype: "list",
            store: "Notes",
            itemId:"notesList",
            loadingText: "Loading Notes...",
            emptyText: '<div class="notes-list-empty-text">No notes found.</div>',
            onItemDisclosure: true,
            grouped: true,
            itemTpl: '<div class="list-item-title">{title}</div><div class="list-item-narrative">{narrative}</div>'
        }],
        listeners: [{
            delegate: "#newButton",
            event: "tap",
            fn: "onNewButtonTap"
        }, {
            delegate: "#notesList",
            event: "disclose",
            fn: "onNotesListDisclose"
        }]
    },
    onNewButtonTap: function () {
        console.log("newNoteCommand");
        this.fireEvent("newNoteCommand", this);
    },
    onNotesListDisclose: function (list, record, target, index, evt, options) {
        console.log("editNoteCommand");
        this.fireEvent('editNoteCommand', this, record);
    }
});


If you are already familiar with the previous version of this View, you will notice that although the onNewButtonTap and onNotesListDisclose functions remain unchanged, we are now taking advantage of the config object to define the Views items, and the event listeners needed for the New button and the disclose buttons of the notes List.


如果你已经对前面的版本很熟悉的话,你会看到虽然onNewButtonTap()onNoteListDisclose()函数没做改变,但是我们却是用了config对象来配置视图的控件和事件。


Defining Event Listeners with Sencha Touch Config Objects(使用STconfig对象定义事件监听器

The New buttons tap listener is pretty straightforward(坦率,直接,简单). Its delegate(代表) config is the value of the itemId config of the button. The fn config is a pointer to the onNewButtonTap function:


newButton的监听器很简单。他的delegate配置是按钮的id,然后fn配置指定事件处理函数。


{
    delegate: "#newButton",
    event: "tap",
    fn: "onNewButtonTap"
}


We defined the Lists disclose handler in a similar fashion. The delegate points to the Lists itemId, and fn is the onNotesListDisclose function:

我们使用相同的风格来定义listdisclose监听器。

{
    delegate: "#notesList",
    event: "disclose",
    fn: "onNotesListDisclose"
}



Configuring the Note Editor(配置noteEditor


Now we are going to move on to the NoteEditor View, where we will replace the initialize function with the configs items and listeners properties:

我们到NoteEditor视图中我们将会用config对象来替换初始化函数中的代码:


Ext.define("NotesApp.view.NoteEditor", {
    extend: "Ext.form.Panel",
    requires: "Ext.form.FieldSet",
    alias: "widget.noteeditorview",
    config: {
        scrollable: 'vertical',
        items: [
            {
                xtype: "toolbar",
                docked: "top",
                title: "Edit Note",
                items: [
                    {
                        xtype: "button",
                        ui: "back",
                        text: "Home",
                        itemId: "backButton"
                    },
                    { xtype: "spacer" },
                    {
                        xtype: "button",
                        ui: "action",
                        text: "Save",
                        itemId: "saveButton"
                    }
                ]
            },
            {
                xtype: "toolbar",
                docked: "bottom",
                items: [
                    {
                        xtype: "button",
                        iconCls: "trash",
                        iconMask: true,
                        itemId: "deleteButton"
                    }
                ]
            },
            { xtype: "fieldset",
                items: [
                    {
                        xtype: 'textfield',
                        name: 'title',
                        label: 'Title',
                        required: true
                    },
                    {
                        xtype: 'textareafield',
                        name: 'narrative',
                        label: 'Narrative'
                    }
                ]
            }
        ],
        listeners: [
            {
                delegate: "#backButton",
                event: "tap",
                fn: "onBackButtonTap"
            },
            {
                delegate: "#saveButton",
                event: "tap",
                fn: "onSaveButtonTap"
            },
            {
                delegate: "#deleteButton",
                event: "tap",
                fn: "onDeleteButtonTap"
            }
        ]
    },
    onSaveButtonTap: function () {
        console.log("saveNoteCommand");
        this.fireEvent("saveNoteCommand", this);
    },
    onDeleteButtonTap: function () {
        console.log("deleteNoteCommand");
        this.fireEvent("deleteNoteCommand", this);
    },
    onBackButtonTap: function () {
        console.log("backToHomeCommand");
        this.fireEvent("backToHomeCommand", this);
    }
});




We are following the same approach we used to configure the NotesList View. This time, we need listeners for the Back, Save and Delete buttons:

遵循在NoteList视图中的配置方法,为backsavedelete按钮配置监听器:


listeners: [
    {
        delegate: "#backButton",
        event: "tap",
        fn: "onBackButtonTap"
    },
    {
        delegate: "#saveButton",
        event: "tap",
        fn: "onSaveButtonTap"
    },
    {
        delegate: "#deleteButton",
        event: "tap",
        fn: "onDeleteButtonTap"
    }
]


The onBackButtonTap, onSaveButtonTap, and onDeleteButtonTap function remain unchanged.

The onBackButtonTap, onSaveButtonTap, and onDeleteButtonTap函数都没有变化。

Adding View Instances to the Application(给应用添加视图引用)

In the app.js file, we are going to instantiate both Views as follows:

app.js文件中,我们这样实例化两个视图:


Ext.application({
    name: "NotesApp",
    models: ["Note"],
    stores: ["Notes"],
    controllers: ["Notes"],
    views: ["NotesList", "NoteEditor"],
    launch: function () {
        var notesListView = {
            xtype: "noteslistview"
        };
        var noteEditorView = {
            xtype: "noteeditorview"
        };
        Ext.Viewport.add([notesListView, noteEditorView]);
    }
});



Modifying the Controller(修改控制器)


The Controller remains unchanged, with the exception of the Views aliases, which we have changed in the chapter of the tutorial:

由于视图类没有

Ext.define("NotesApp.controller.Notes", {
    extend: "Ext.app.Controller",
    config: {
        refs: {
            // We're going to lookup our views by alias.
            notesListView: "noteslistview",
            noteEditorView: "noteeditorview",
            notesList: "#notesList"
        },
        control: {
            notesListView: {
                // The commands fired by the notes list container.
                newNoteCommand: "onNewNoteCommand",
                editNoteCommand: "onEditNoteCommand"
            },
            noteEditorView: {
                // The commands fired by the note editor.
                saveNoteCommand: "onSaveNoteCommand",
                deleteNoteCommand: "onDeleteNoteCommand",
                backToHomeCommand: "onBackToHomeCommand"
            }
        }
    },
    // Transitions
    slideLeftTransition: { type: 'slide', direction: 'left' },
    slideRightTransition: { type: 'slide', direction: 'right' },
    // Helper functions
    getRandomInt: function (min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    },
    activateNoteEditor: function (record) {
        var noteEditorView = this.getNoteEditorView();
        noteEditorView.setRecord(record); // load() is deprecated.
        Ext.Viewport.animateActiveItem(noteEditorView, this.slideLeftTransition);
    },
    activateNotesList: function () {
        Ext.Viewport.animateActiveItem(this.getNotesListView(), this.slideRightTransition);
    },
    // Commands.
    onNewNoteCommand: function () {
        console.log("onNewNoteCommand");
        var now = new Date();
        var noteId = (now.getTime()).toString() + (this.getRandomInt(0, 100)).toString();
        var newNote = Ext.create("NotesApp.model.Note", {
            id: noteId,
            dateCreated: now,
            title: "",
            narrative: ""
        });
        this.activateNoteEditor(newNote);
    },
    onEditNoteCommand: function (list, record) {
        console.log("onEditNoteCommand");
        this.activateNoteEditor(record);
    },
    onSaveNoteCommand: function () {
        console.log("onSaveNoteCommand");
        var noteEditorView = this.getNoteEditorView();
        var currentNote = noteEditorView.getRecord();
        var newValues = noteEditorView.getValues();
        // Update the current note's fields with form values.
        currentNote.set("title", newValues.title);
        currentNote.set("narrative", newValues.narrative);
        var errors = currentNote.validate();
        if (!errors.isValid()) {
            Ext.Msg.alert('Wait!', errors.getByField("title")[0].getMessage(), Ext.emptyFn);
            currentNote.reject();
            return;
        }
        var notesStore = Ext.getStore("Notes");
        if (null == notesStore.findRecord('id', currentNote.data.id)) {
            notesStore.add(currentNote);
        }
        notesStore.sync();
        notesStore.sort([{ property: 'dateCreated', direction: 'DESC'}]);
        this.activateNotesList();
    },
    onDeleteNoteCommand: function () {
        console.log("onDeleteNoteCommand");
        var noteEditorView = this.getNoteEditorView();
        var currentNote = noteEditorView.getRecord();
        var notesStore = Ext.getStore("Notes");
        notesStore.remove(currentNote);
        notesStore.sync();
        this.activateNotesList();
    },
    onBackToHomeCommand: function () {
        console.log("onBackToHomeCommand");
        this.activateNotesList();
    },
    // Base Class functions.
    launch: function () {
        this.callParent(arguments);
        var notesStore = Ext.getStore("Notes");
        notesStore.load();
        console.log("launch");
    },
    init: function () {
        this.callParent(arguments);
        console.log("init");
    }
});



Summary


We just created a version of the Notes Application where, instead of the initialize function, we exclusively(仅仅) used config objects to configure each of the applications Views. In the process(在此过程中), we learned how to create event listeners for components defined using config objects.

At this point, we have accomplished our goals for this application. I hope the insights(见解) you gained in this Sencha Touch tutorial will help you create great mobile applications.


这里我们只是创建了一个使用config对象配置视图的版本。我们仅仅使用config配置应用的视图,在这个过程中我们学习了怎么使用config对象为控件创建事件监听。

到此为止我们已经能实现了我们的目标,希望这个教程能给你一些灵感,让你创造出更加好的移动应用!


Downloads


Download the source code for this article: NotesApp-ST2-Part5.zip

The Entire Series

§ How to Create a Sencha Touch 2 App, Part 1

§ How to Create a Sencha Touch 2 App, Part 2

§ How to Create a Sencha Touch 2 App, Part 3

§ How to Create a Sencha Touch 2 App, Part 4

§ How to Create a Sencha Touch 2 App, Part 5

§ 

Want To Learn More?

My Sencha Touch books will teach you how to create an application from scratch.

§ Sencha Touch 2 Book

§ Sencha Touch 1 Book

What Sencha Touch Topics Would You Like Me To Write About?

Id like to help you learn Sencha Touch better and faster, but I need you to let me know what subjects you are curious about, or what topics you are struggling with.

Please send me your questions or suggestions for future posts at miamicoder[AT]gmail.com.

TAGGED WITH: SENCHA TOUCH TUTORIAL 58 COMMENTS

About Jorge

Jorge is the author of Building a Sencha Touch ApplicationHow to Build a jQuery Mobile Application, and the Ext JS 3.0 Cookbook. He runs a software development and developer education shop that focuses on mobile, web and desktop technologies.

If you'd like to work with Jorge, contact him at ramonj[AT]miamicoder.com.

你可能感兴趣的:(UI,list,function,Class,action,button)