Статьи

BackBone Tutorial — Часть 3. Больше о моделях Backbone

В этой статье мы рассмотрим еще несколько концепций, связанных с базовыми моделями. Мы попытаемся увидеть, как мы можем переопределить поведение модели по умолчанию. Мы рассмотрим значение идентификаторов моделей, как мы можем проверить модель и, наконец, как модель может быть сохранена либо локально, либо на сервере.

Ссылка на полную серию:

  1. BackBone Tutorial — Часть 1. Введение в Backbone.Js
  2. BackBone Tutorial — Часть 2. Понимание основ моделей Backbone 
  3. Руководство по BackBone — часть 3: подробнее о моделях Backbone [ ^ ]
  4. BackBone Tutorial — Часть 4. Операции CRUD на моделях BackboneJs, использующих службу HTTP REST [ ^ ]
  5. Руководство по BackBone — часть 5: Понимание коллекций Backbone.js [ ^ ]
  6. Руководство по BackBone — часть 6: Понимание представлений Backbone.js [ ^ ]
  7. BackBone Tutorial — Часть 7. Понимание маршрутов и истории Backbone.js [ ^ ]

Функция Initialize и конструктор

Всякий раз, когда мы создаем модель, магистраль будет вызывать функцию инициализации. Мы можем переопределить эту функцию, чтобы предоставить ей собственное поведение.

var Book = Backbone.Model.extend({
    defaults: {
        ID: "",
        BookName: ""
    },
    initialize: function () {
        console.log('Book has been intialized');       
    },
});

Поэтому, когда мы создадим этот объект, результат будет:

onlyInit

Внутренне происходит то, что всякий раз, когда создается базовая модель, вызывается ее конструктор. Конструктор вызовет функцию initialize. Также возможно предоставить собственный конструктор и обеспечить пользовательское поведение.

var Book = Backbone.Model.extend({
    defaults: {
        ID: "",
        BookName: ""
    },
    initialize: function () {
        console.log('Book has been intialized');       
    },
    constructor: function (attributes, options) {
        console.log('Book\'s constructor had been called');
    },
});

Вывод при создании этой модели:

onlyConstructor

Теперь проблема с этим конструктором заключается в том, что всякий раз, когда создается базовая модель, вызывается наш конструктор. Но конструктор по умолчанию также выполняет много других действий во время создания объекта, например, вызывает функцию initialize. Таким образом, чтобы убедиться, что наш пользовательский конструктор работает в унисон со всем этим поведением по умолчанию, нам нужно сообщить базовой платформе, что мы все еще хотим это поведение по умолчанию. Это можно сделать, вызвав Backbone.Model.apply (this, arguments); в конце нашего пользовательского конструктора. Это обеспечит вызов нашего пользовательского конструктора, а затем все остальные действия, которые должен выполнять конструктор по умолчанию, также будут выполнены.

var Book = Backbone.Model.extend({
    defaults: {
        ID: "",
        BookName: ""
    },
    initialize: function () {
        console.log('Book has been intialized');       
    },
    constructor: function (attributes, options) {
        console.log('Book\'s constructor had been called');
        Backbone.Model.apply(this, arguments);
    },
});

Теперь вывод будет:

rightConstructor

Примечание. Для большинства практических целей достаточно переопределить функцию инициализации. Редко возникает необходимость переопределить конструктор, но если кто-то решит переопределить конструктор, это должен быть способ сделать это.

Идентификаторы модели — id, cid и idAttribute

Каждая модель должна быть уникально идентифицирована. Для этого магистраль дает нам идентификаторы модели. Первый, который нужно посмотреть, это cid. Идентификатор cid или client является автоматически генерируемым магистралью, так что каждая модель может быть уникально идентифицирована на клиенте.

var book1 = new Book();
var book2 = new Book();

чид

Backbone также предоставляет идентификатор идентификатора, чтобы однозначно идентифицировать объект модели. Это идентификатор, который будет использоваться для идентификации модели, когда данные модели фактически синхронизируются с сервером, то есть сохраняются. cid более полезен для целей отладки, но атрибут id будет определять уникальность модели, когда речь идет об операциях CRUD на модели. Его довольно просто установить и получить свойство id.

var book2 = new Book();
book2.id = 3;
console.log(book2.id);

Выход для вышеуказанного кода будет: 3 .

Теперь это становится немного запутанным в этой точке. Поскольку большинство наших моделей будет иметь атрибут, который будет соответствовать первичному ключу / уникальному идентификатору объекта. Нужно ли явно устанавливать значение id для этого атрибута. Ответ если да и нет. Мы должны каким-то образом указать базовой модели, какой атрибут следует использовать в качестве идентификатора, но нам не нужно явно устанавливать идентификатор. мы можем использовать idAttribute для достижения этой цели.

var Book = Backbone.Model.extend({
    defaults: {
        ID: "",
        BookName: ""
    },
    idAttribute: "ID",
    initialize: function () {
        console.log('Book has been intialized');
    },
    constructor: function (attributes, options) {
        console.log('Book\'s constructor had been called');
        Backbone.Model.apply(this, arguments);
    },
});

Теперь в приведенном выше коде мы указали, что идентификатор следует использовать как идентификатор, указав idAttribute. Попробуем сейчас создать новую модель со значением ID.

var book3 = new Book({ ID: 43 });
console.log(book1.id);

И мы видим, что значение id берется из указанного атрибута.

idAttribute

и, таким образом, это облегчает работу базовых моделей с объектами на стороне сервера и делает идентификацию модели беспроблемной.

Проверка модели

Когда мы работаем над бизнес-приложениями, часто требуется проверить модель перед сохранением данных. Backbone обеспечивает очень простой способ проверки данных модели. Нам просто нужно реализовать функцию проверки моделей.

var Book = Backbone.Model.extend({
    defaults: {
        ID: "",
        BookName: ""
    },
    idAttribute: "ID",
    initialize: function () {
        console.log('Book has been intialized');
    },
    constructor: function (attributes, options) {
        console.log('Book\'s constructor had been called');
        Backbone.Model.apply(this, arguments);
    },
    validate: function (attr) {
        if (attr.ID <= 0) {
            return "Invalid value for ID supplied."
        }
    }
});

Здесь происходит то, что всякий раз, когда мы пытаемся сохранить модель (которую мы увидим в следующем разделе), вызывается функция Validate. Он проверит установленную нами логику проверки и проверит модель. Чтобы протестировать метод validate, мы можем использовать функцию models isValid.

var book4 = new Book({ ID: -4 });
var result = book4.isValid(); // false

Еще один способ предотвратить недопустимые значения в атрибутах модели — передать значение validate: true при установке атрибута models. Это также вызовет функцию проверки

var book5 = new Book();
book5.set("ID", -1, {validate:true});

Что это будет делать, так это то, что это даже не позволит установить недопустимые значения, если значение, которое мы пытаемся установить, является недопустимым согласно нашей пользовательской логике.

Как работает эта проверка, так это то, что всякий раз, когда пользователь выбирает сохранение модели, вызывается функция проверки. если есть какая-либо ошибка проверки, то сохранение модели завершится неудачно. в качестве альтернативы пользователь может выбрать значение validate: true всякий раз, когда он хочет ограничить установку недопустимых значений в атрибутах модели.

Если мы хотим проверить достоверность модели в любом конкретном случае, мы можем использовать функцию isValid для проверки этого. Сказав, что здесь важно знать одну вещь, это то, что, когда наша функция проверки не может проверить модель, событие вызывает недействительное основание. Если мы хотим прослушать это событие, мы можем подписаться на это.

Попробуем подключиться к этому событию и увидеть ошибки проверки. Мы сделаем это в функции инициализации модели.

var Book = Backbone.Model.extend({
    defaults: {
        ID: "",
        BookName: ""
    },
    idAttribute: "ID",
    initialize: function () {
        console.log('Book has been intialized');
        this.on("invalid", function (model, error) {
            console.log("Houston, we have a problem: " + error)
        });
    },
    constructor: function (attributes, options) {
        console.log('Book\'s constructor had been called');
        Backbone.Model.apply(this, arguments);
    },
    validate: function (attr) {
        if (attr.ID <= 0) {
            return "Invalid value for ID supplied."
        }
    }
});

validationHook

Сохранение модели

Базовые модели по своей природе поддерживают сохранение на сервере с помощью полноценного веб-API. Чтобы сохранить модель с помощью службы HTTP REST, нам нужно указать urlRoot в базовой модели. Чтобы реально сохранить модель, мы можем вызвать сохранение в базовой модели. Метод save будет запускать проверки и, если проверки успешны, он попытается определить действие, которое необходимо выполнить, т.е. создать или обновить, и на основе этого действия он будет использовать urlRoot и вызовет соответствующий API REST для выполнения операции.

Поэтому, если у меня есть служба, работающая на моей локальной машине, мне сначала нужно указать urlRoot для службы в моей модели.

var Book = Backbone.Model.extend({
    defaults: {
        ID: "",
        BookName: ""
    },
    idAttribute: "ID",
    initialize: function () {
        console.log('Book has been initialized');
        this.on("invalid", function (model, error) {
            console.log("Houston, we have a problem: " + error)
        });
    },
    constructor: function (attributes, options) {
        console.log('Book\'s constructor had been called');
        Backbone.Model.apply(this, arguments);
    },
    validate: function (attr) {
        if (attr.ID <= 0) {
            return "Invalid value for ID supplied."
        }
    },
    urlRoot: 'http://localhost:51377/api/Books'
});

и чтобы сохранить эту модель с помощью этого сервиса, я мог бы сделать что-то вроде:

var book = new Book({ BookName: "Backbone Book 43" });
    book.save({}, {
        success: function (model, response, options) {
            console.log("The model has been saved to the server");
        },
        error: function (model, xhr, options) {
            console.log("Something went wrong while saving the model");
        }
    });

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

Теперь, если мы хотим сохранить модель в локальном хранилище, а не на сервере, нам нужно просто помнить, что функция сохранения фактически вызывает функцию синхронизации для фактического сохранения / получения информации о модели. Поэтому, если нам нужно сохранить модель в локальном хранилище, нам необходимо переопределить функцию синхронизации и предоставить собственный код для сохранения в локальном хранилище.

Примечание . Код, показанный выше (для модели сохранения), синтаксически правильный, но он не будет работать, если у нас не запущена служба REST с упомянутым urlRoot. В следующих статьях я подробно объясню, как сохранить модель с помощью службы REST, а также с примером службы и HTML-кодом.

Достопримечательность

Итак, мы увидели еще несколько деталей о моделях магистрали. Мы еще не рассматривали, как сохранить модель ни локально, ни с помощью службы. Возможно, в моих следующих статьях мы поговорим только об этом.

Загрузить пример кода для этой статьи:  backboneModelsSample2