среда, 31 июля 2013 г.

Коротко о Backbone

Установка Backbone.js

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
         <script src="js/underscore.js"></script>
         <script src="js/jquery.js"></script>
         <script src="js/backbone.js"></script>
        <title>Backbone</title>
    </head>
    <body>
    </body>
</html>

Теперь откройте HTML-файл и наберите в консоли:

Backbone

Вы увидите следующий результат:
























Представление данных в JavaScript в виде объекта

var Person = function(config){
    this.name = config.name;
    this.age = config.age;
    this.occupation = config.occupation;
};

Person.prototype.work = function(){
    return this.name + ' is working.';
};

var person = new Person({name: "Mohit Jain", age: 25, occupation: "Software Developer"});

person.name;          // выведет значение name объекта person
person.age;             // выведет значение age объекта person
person.occupation;  // выведет значение occupation объекта person
person.work();        // выполнится функция work объекта person

При наборе данного кода в консоли вы увидите:















Создание Model

var Person = Backbone.Model.extend({
    defaults: {
        name: 'Guest User',
        age: 23,
        occupation: 'Worker'
    },
    work: function(){
        return this.get('name') + ' is working.';
    }
});

var person = new Person({name:"Taroon Tyagi", age: 26, occupation: "Graphics Designer"});

// Или var person = new Person(); для установки значений, прописанных по умолчанию в defaults

person.get('name');       // выведет значение name прописанное по умолчанию для объекта person
person.get('age');          // выведет значение age прописанное по умолчанию для объекта person
person.get('occupation'); // выведет значение occupation прописанное по умолчанию для объекта person

Установка новых значений для объекта Model

person.set('name', 'Taroon Tyagi');             // установит новое значение name для объекта person
person.set('age', 26);                                // установит новое значениеage для объекта person
person.set('occupation', 'Graphics Designer'); // установит новое значение occupation для объекта person

person.set({name:"Taroon Tyagi", age: 26, occupation: "Graphics Designer"}); // Установит сразу новый набор значений для объекта person

Вывод всех значений из объекта Model в формате объекта JSON

person.toJSON(); // вернет все свойства данного объекта





































Валидация данных перед вставкой в Model

var Person = Backbone.Model.extend({
    defaults: {
        name: 'Guest User',
        age: 23,
        occupation: 'worker'
    },

    validate: function(attributes){
        if ( attributes.age < 0){
            return 'Age must be positive.';
        }

        if ( !attributes.name ){
            return 'Every person must have a name.';
        }
    },

    work: function(){
        return this.get('name') + ' is working.';
    }
});

var person = new Person({name: "Mohit Jain", age: -1, occupation: "Software Developer"}) // Такой способ добавления данных при создании объекта модели не вызовет срабатывания метода validate. Метод validate будет вызван только при использовании метода set()
person.get('age') // вернет значение -1

var person = new Person();
person.set('age', -1) // Попытка установить значение -1 при прохождении валидации в методе validate вернет false и значение установлено не будет
person.set('age', 18) // Попытка установить значение 18 при прохождении валидации в методе validate вернет true и значение установлено будет

Как увидеть сообщение об ошибке при прохождении валидации?

Для этого необходимо добавить обработчик события on('error')

person.on('error', function(model, error){
    console.log(error); // Вывод сообщения возвращаемого через return функцией validate
});

Теперь установка неверного значения выведет сообщение в консоль.

person.set("age", -1) // Попытка установить значение -1 при прохождении валидации в методе validate вернет false, значение установлено не будет и в консоль будет выведено сообщение об ошибке возвращенное из функции validate

Создание View

var Person = Backbone.Model.extend({
    defaults: {
        name: 'Guest User',
        age: 23,
        occupation: 'worker'
    }
});

var PersonView = Backbone.View.extend({
   tagName: 'li',

   initialize: function(){
     this.render();
   },

   render: function(){
     this.$el.html( this.model.get('name') + ' ' + this.model.get('age') + ' ' + this.model.get('occupation') );
  }
});


var person = new Person(); // Создаем объект модели
var personView = new PersonView({ model: person }); // Создаем объект View и отрисовываем (рендерим) содержимое внутри элемента el.

$('body').html(personView.el); // Вставляем отрисованное (отрендеренное) содержимое в элементе el на страницу

// personView.el   // Выводит содержимое отрендеренное в данный момент в элементе el нашего объекта View

Использование шаблонов Template при рендеринге View

var Person = Backbone.Model.extend({
    defaults: {
        name: 'Guest Worker',
        age: 23,
        occupation: 'worker'
    }
});

var PersonView = Backbone.View.extend({
    tagName: 'li',

    my_template: _.template('<strong><%= name %></strong> (<%= age %>) - <%= occupation %>'),

    initialize: function(){
        this.render();
    },

    render: function(){
        this.$el.html( this.my_template( this.model.toJSON() ) );
    }
});

var person = new Person(); // Создаем объект модели
var personView = new PersonView({ model: person }); // Создаем объект View и отрисовываем (рендерим) содержимое внутри элемента el, подставляя содержимое в шаблон  my_template
$('body').html(personView.el); // Вставляем отрисованное (отрендеренное) содержимое в элементе el на страницу

// personView.el   // Выводит содержимое отрендеренное в данный момент в элементе el нашего объекта View

Усовершенствуем использование шаблонов Template при рендеринге View

Поместим код шаблона в HTML-код страницы внутрь тэгов <script>

<script id="personTemplate" type="text/template">
    <strong><%= name %></strong> (<%= age %>) - <%= occupation %>
</script>

И будем брать содержимое для шаблона из этого кода

var Person = Backbone.Model.extend({
    defaults: {
        name: 'Guest Worker',
        age: 23,
        occupation: 'worker'
    }
});

var PersonView = Backbone.View.extend({
    tagName: 'li',

    my_template: _.template( $('#personTemplate').html()),

    initialize: function(){
        this.render();
    },

    render: function(){
        this.$el.html( this.my_template( this.model.toJSON() ) );
    }
});

var person = new Person(); // Создаем объект модели
var personView = new PersonView({ model: person }); // Создаем объект View и отрисовываем (рендерим) содержимое внутри элемента el, подставляя содержимое в шаблон  my_template
$('body').html(personView.el); // Вставляем отрисованное (отрендеренное) содержимое в элементе el на страницу

// personView.el   // Выводит содержимое отрендеренное в данный момент в элементе el нашего объекта View

Создание Collection

// Person Model
var Person = Backbone.Model.extend({
    defaults: {
        name: 'Guest User',
        age: 30,
        occupation: 'worker'
    }
});

// A List of People
var PeopleCollection = Backbone.Collection.extend({
    model: Person
});

// The View for a Person
var PersonView = Backbone.View.extend({
    tagName: 'li',

    template: _.template( $('#personTemplate').html()),

    initialize: function(){
        this.render();
    },

    render: function(){
        this.$el.html( this.template(this.model.toJSON()));
    }
});



var person = new Person(); // Создаем объект модели
var personView = new PersonView({ model: person }); // Создаем объект View
var peopleCollection = new PeopleCollection(); // Создаем объект Collection

peopleCollection.add(person); // Добавляем объект модели в коллекцию

var person2 = new Person({name: "Mohit Jain", age: 25, occupation: "Software Developer"}); // Создаем второй объект модели
var personView2 = new PersonView({ model: person2 }); / Создаем второй объект View

peopleCollection.add(person2); // Добавляем второй объект модели в коллекцию

console.log(peopleCollection); // Выводи в консоль все содержимое коллекции
console.log(peopleCollection.toJSON()); // Выводи в консоль все содержимое коллекции в формате JSON

































Другой способ добавления объектов Model в Collection

// Person Model
var Person = Backbone.Model.extend({
    defaults: {
        name: 'Guest User',
        age: 30,
        occupation: 'worker'
    }
});

// A List of People
var PeopleCollection = Backbone.Collection.extend({
    model: Person
});

// The View for a Person
var PersonView = Backbone.View.extend({
    tagName: 'li',

    template: _.template( $('#personTemplate').html()),

    initialize: function(){
        this.render();
    },

    render: function(){
        this.$el.html( this.template(this.model.toJSON()));
    }
});

var peopleCollection = new PeopleCollection([
    {
        name: 'Mohit Jain',
        age: 26
    },
    {
        name: 'Taroon Tyagi',
        age: 25,
        occupation: 'web designer'
    },
    {
        name: 'Rahul Narang',
        age: 26,
        occupation: 'Java Developer'
    }
]);


Создание View для вывода данных из Collection

// Person Model
var Person = Backbone.Model.extend({
    defaults: {
        name: 'Guest User',
        age: 30,
        occupation: 'worker'
    }
});

// A List of People
var PeopleCollection = Backbone.Collection.extend({
    model: Person
});

// View for all people
var PeopleView = Backbone.View.extend({
    tagName: 'ul',
    render: function(){
        this.collection.each(function(person){
            var personView = new PersonView({ model: person });
            this.$el.append(personView.render().el); // calling render method manually..
        }, this);
        return this; // возвращаем this для создания цепочки вызовов
    }
});

// The View for a Person
var PersonView = Backbone.View.extend({
    tagName: 'li',
    template: _.template($('#personTemplate').html()),
    // initialize - данная функция отсюда исчезла, поэтому нам нужно вызвать метод render вручную
    render: function(){
        this.$el.html( this.template(this.model.toJSON()));
        return this;  // возвращаем this из метода render
    }
});

var peopleCollection = new PeopleCollection([
    {
        name: 'Mohit Jain',
        age: 26
    },
    {
        name: 'Taroon Tyagi',
        age: 25,
        occupation: 'web designer'
    },
    {
        name: 'Rahul Narang',
        age: 26,
        occupation: 'Java Developer'
    }
]);

var peopleView = new PeopleView({ collection: peopleCollection }); // Создание объекта PeopleView

$(document.body).append(peopleView.render().el);   // Добавление peopleView на страницу






















Упрощение загрузки Template во View из HTML-кода

Обычно шаблон Template располагается в HTML-коде внутри тэгов <script>

<script id="personTemplate" type="text/template">
    <strong><%= name %></strong> (<%= age %>) - <%= occupation %>
</script>

Данный шаблон поступает по View так:

template: _.template( $('#personTemplate').html()),

Однако мы можем создать некую независимую функцию-помощьник, которая позволит гораздо проще загружать код шаблона в любой View

var template = function(id) {
    return _.template( $('#' + id).html());
};

Таким образом в каждом View мы может использовать эту функцию для загрузки шаблонов так:

template: template('personTemplate'),

Использование Namespacing для организации кода

Person
PersonView
PeopleCollection
PeopleView

// Теперь тоже самое с использованием namespace

App.Models.Person
App.Views.PersonView
App.Collections.PeopleCollection
App.Views.PeopleView

// Данный код мы можем спокойно сократить до такого состояния

App.Models.Person
App.Views.Person
App.Collections.People
App.Views.People

Теперь используя Namespacing весь наш код мы можем записать так:

(function(){  // Весь код мы записываем в формате модуля, чтобы избежать засорения глобального пространства имен

    window.App = { // созданим namespce App для нашего приложения
        Models: {},
        Collections: {},
        Views: {}
    };

    window.template = function(id){
        return _.template( $('#' + id).html());
    };


    // Person Model
    App.Models.Person = Backbone.Model.extend({   // Модель Person помещается в пространство имен App нашего приложения
        defaults: {
            name: 'Guest User',
            age: 30,
            occupation: 'worker'
        }
    });

    // A List of People
    App.Collections.People = Backbone.Collection.extend({ // Коллекция People помещается в пространство имен App нашего приложения
        model: App.Models.Person  // Модель для коллекции берется из пространства имен App нашего приложения
    });


    // View for all people
    App.Views.People = Backbone.View.extend({ // View People помещается в пространство имен App нашего приложения
        tagName: 'ul',

        render: function(){
            this.collection.each(function(person){
                var personView = new App.Views.Person({ model: person });
                this.$el.append(personView.render().el);
            }, this);

            return this;
        }
    });

    // The View for a Person
    App.Views.Person = Backbone.View.extend({ // View Person помещается в пространство имен App нашего приложения
        tagName: 'li',

        template: template('personTemplate'),
        render: function(){
            this.$el.html( this.template(this.model.toJSON()));
            return this;
        }
    });

    var peopleCollection = new App.Collections.People([
        {
            name: 'Mohit Jain',
            age: 26
        },
        {
            name: 'Taroon Tyagi',
            age: 25,
            occupation: 'web designer'
        },
        {
            name: 'Rahul Narang',
            age: 26,
            occupation: 'Java Developer'
        }
    ]);


    var peopleView = new App.Views.People({ collection: peopleCollection });
    $(document.body).append(peopleView.render().el);

})();

Создание событий Events

// The View for a Person
App.Views.Person = Backbone.View.extend({
    tagName: 'li',
    template: template('personTemplate'),

    initialize: function(){
        this.model.on('change', this.render, this);
    },

    events: {
     'click' : 'showAlert',
     'click .edit' : 'editPerson',
     'click .delete' : 'DestroyPerson'
    },

    showAlert: function(){
        alert("You clicked me");
    },

    editPerson: function(){
        var newName = prompt("Please enter the new name", this.model.get('name'));
        this.model.set('name', newName);
    },

    DestroyPerson: function(){
        this.model.destroy();
    },


    render: function(){
        this.$el.html( this.template(this.model.toJSON()));
        return this;
    }
});

Связывание событий с элементами формы

<form id="addPerson" action="">
        <input type="text" placeholder="Name of the person">
        <input type="submit" value="Add Person">
</form>

App.Views.AddPerson = Backbone.View.extend({
    el: '#addPerson',  # referencing the form itself.

    events: {
        'submit': 'submit'
    },

    submit: function(e){
        e.preventDefault();
        var newPersonName = $(e.currentTarget).find('input[type=text]').val();
        var person = new App.Models.Person({ name: newPersonName });
        this.collection.add(person);
    }
});

// View for all people
App.Views.People = Backbone.View.extend({
    tagName: 'ul',

    initialize: function(){
        this.collection.on('add', this.addOne, this);
    },
    render: function(){
        this.collection.each(this.addOne, this);
        return this;
    },

    addOne: function(person){
        var personView = new App.Views.Person({ model: person });
        this.$el.append(personView.render().el);
    }
});

var addPersonView = new App.Views.AddPerson({ collection: peopleCollection });
peopleView = new App.Views.People({ collection: peopleCollection });
$(document.body).append(peopleView.render().el);

Создание Router

(function(){

    window.App = {
        Models: {},
        Collections: {},
        Views: {},
        Router: {}
    };

    App.Router = Backbone.Router.extend({
        routes: {
            '': 'index',
            'show/:id': 'show',
            'download/*random': 'download',
            'search/:query': 'search',
            '*default': 'default'
        },

        index: function(){
            $(document.body).append("Index route has been called..");
        },

        show: function(id){
            $(document.body).append("Show route has been called.. with id equals : "   id);
        },

        download: function(random){
            $(document.body).append("download route has been called.. with random equals : "   random);
        },

        search: function(query){
            $(document.body).append("Search route has been called.. with query equals : "   query);
        },

        default: function(default){
            $(document.body).append("This route is not hanled.. you tried to access: "   default);

        }
       
    });

    new App.Router;
    Backbone.history.start();

})();

Комментариев нет:

Отправить комментарий