Що є двостороннім обов'язковим?


173

Я читав багато, що Backbone не робить двосторонній зв'язок, але я не точно розумію цю концепцію.

Чи може хтось надати мені приклад того, як двостороння прив'язка працює в кодовій базі MVC і як це не відбувається з Backbone?

Відповіді:


249

Двостороння прив'язка просто означає, що:

  1. Коли властивості моделі оновлюються, то і інтерфейс користувача.
  2. Коли елементи інтерфейсу оновлюються, зміни повертаються до моделі.

Магістральна система не має "вбудованої" реалізації №2 (хоча ви, звичайно, можете це зробити, використовуючи слухачів подій). Інші рамки, такі як Knockout, здійснюють автоматичне підключення двостороннього зв’язку .


У системі Backbone ви можете легко досягти №1, прив’язавши метод "візуалізації" представлення до події "зміни" своєї моделі. Щоб досягти №2, вам також потрібно додати вхідний елемент до слухача змін і зателефонувати model.setв обробник.

Ось Загадка з двостороннім прив'язкою, встановленою в Backbone.


25
Відповідь настільки болісно очевидна, як тільки ви її бачите. Дуже дякую, що знайшли час, щоб дати чітку відповідь та приклад.
Кріс М

І з Firebase виходить ... 3-х напрямне прив'язування даних -> Перегляд, модель, база даних. Просто подумав, що це було досить акуратно.
Леві Фуллер

Лаконічний і короткий. +1
Karan_powered_by_RedBull

46

Двостороння прив'язка означає, що будь-які зміни, пов’язані з даними, що впливають на модель, негайно поширюються на відповідний вид (и) і що будь-які зміни, внесені в представлення (и) (скажімо, користувачем), негайно відображаються в базовій моделі . Коли дані програми змінюються, змінюється і інтерфейс користувача, і навпаки.

Це дуже солідна концепція побудови веб-додатку поверх, оскільки це робить абстракцію «Модель» безпечним, атомним джерелом даних, яке можна використовувати скрізь у програмі. Скажіть, якщо модель, прив’язана до подання, змінюється, то її відповідна частина інтерфейсу (перегляду) відображатиме це, незважаючи ні на що . І відповідна частина інтерфейсу користувача (подання) може бути безпечно використана як засіб збору входів / даних користувачів, щоб підтримувати актуальні дані програми.

Хороша двостороння обов'язкова реалізація, очевидно, повинна зробити цей зв'язок між моделлю та деякими переглядами якомога простішим з точки зору розробника.

Тоді зовсім неправдиво сказати, що Backbone не підтримує двостороннє прив'язування: хоча це не є основною особливістю фреймворку, його можна виконати досить просто, використовуючи події Backbone's. Це коштує кілька явних рядків коду для простих випадків; і може стати досить небезпечним для складніших прив’язок. Ось простий випадок (неперевірений код, написаний на льоту просто заради ілюстрації):

Model = Backbone.Model.extend
  defaults:
    data: ''

View = Backbone.View.extend
  template: _.template("Edit the data: <input type='text' value='<%= data %>' />")

  events:
    # Listen for user inputs, and edit the model.
    'change input': @setData

  initialize: (options) ->
    # Listen for model's edition, and trigger UI update
    @listenTo @model, 'change:data', @render

  render: ->
    @$el.html @template(@model.attributes)
    @

  setData: (e) =>
    e.preventDefault()
    @model.set 'data', $(e.currentTarget).value()

model: new Model()
view = new View {el: $('.someEl'), model: model}

Це досить типовий зразок у сирому додатку "Хребна". Як видно, для цього потрібна пристойна кількість (досить стандартного) коду.

AngularJS та деякі інші альтернативи ( Ember , Knockout …) забезпечують двостороннє прив'язування як особливість першого громадянина. Вони абстрагують багато кращих справ у деяких DSL і роблять все можливе, інтегруючи двосторонній зв'язок у свою екосистему. Наш приклад виглядав би приблизно так із AngularJS (неперевірений код, див. Вище):

<div ng-app="app" ng-controller="MainCtrl">
  Edit the data:
  <input name="mymodel.data" ng-model="mymodel.data">
</div>
angular.module('app', [])
  .controller 'MainCtrl', ($scope) ->
    $scope.mymodel = {data: ''}

Досить короткий!

Але слід пам'ятати , що деякі Повноцінна двостороння розширення зв'язування дійсно існують для Backbone , а також (в сирому, суб'єктивному порядку убування складності): епоксидна , StickIt , ModelBinder ...

Наприклад, одна з прихильних функцій Epoxy - це те, що вона дозволяє оголошувати свої прив'язки (атрибути моделі <-> перегляд елемента DOM) або в межах шаблону (DOM), або в межах реалізації перегляду (JavaScript). Деякі люди сильно не люблять додавати "директиви" до DOM / шаблону (наприклад, атрибути ng- *, необхідні AngularJS, або атрибути прив'язки даних Ember).

Взявши за приклад Epoxy, можна переробити необроблений додаток Backbone у щось подібне (…):

Model = Backbone.Model.extend
  defaults:
    data: ''

View = Backbone.Epoxy.View.extend
  template: _.template("Edit the data: <input type='text' />")
  # or, using the inline form: <input type='text' data-bind='value:data' />

  bindings:
    'input': 'value:data'

  render: ->
    @$el.html @template(@model.attributes)
    @

model: new Model()
view = new View {el: $('.someEl'), model: model}

Загалом, майже всі рамки JS "mainstream" підтримують двостороння прив'язка. Деякі з них, як-от Backbone, вимагають додаткової роботи, щоб зробити це безперебійним , але ті ж, що не застосовують певного способу зробити це, для початку. Тож мова йде справді про ваш душевний стан.

Також вас може зацікавити Flux , інша архітектура веб-додатків, що рекламують одностороннє прив'язування за допомогою кругового шаблону. Він заснований на концепції швидкого цілісного відтворення компонентів інтерфейсу користувача при будь-якій зміні даних для забезпечення згуртованості та полегшення міркування про код / ​​потік даних. У тій же тенденції, ви можете перевірити концепцію MVI (Model-View-Intent), наприклад, Cycle .


3
Багато розробників, особливо розробники React / Flux, не вважають двосторонню прив'язку безпечною схемою для створення великих масштабних додатків.
Енді

28

У McGarnagle є чудова відповідь, і ви хочете прийняти його, але я подумав, що я згадаю (оскільки ви запитали), як працює прив'язка даних.

Він, як правило, реалізується шляхом запуску подій кожного разу, коли вноситься зміна даних, що призводить до оновлення слухачів (наприклад, інтерфейсу користувача).

Двостороння прив'язка працює, виконуючи це двічі, дотримуючись певної обережності, щоб ви не зациклювалися на циклі подій (де оновлення з події спричиняє звільнення іншої події).

Я збирався викласти це в коментарі, але це стало досить довго ...


2

Насправді emberjsпідтримує двостороннє прив'язування, що є однією з найпотужніших функцій рамки java MVC. Ви можете перевірити, де це згадується, bindingу своєму посібнику користувача.

для emberjs створити двостороння прив'язка - це створити нове властивість із рядком Binding в кінці, а потім вказати шлях із глобальної області застосування:

App.wife = Ember.Object.create({
  householdIncome: 80000
});

App.husband = Ember.Object.create({
  householdIncomeBinding: 'App.wife.householdIncome'
});

App.husband.get('householdIncome'); // 80000

// Someone gets raise.
App.husband.set('householdIncome', 90000);
App.wife.get('householdIncome'); // 90000

Зауважте, що прив'язки не оновлюються одразу. Ембер чекає, поки весь код вашої програми закінчиться, перш ніж синхронізувати зміни, тож ви можете змінити прив’язане властивість стільки разів, скільки хочете, не турбуючись про накладні витрати синхронізації, коли значення минущі.

Сподіваюсь, це допоможе розширити обрану оригінальну відповідь.


1

Варто зазначити, що існує багато різних рішень, які пропонують двосторонній зв'язок і дуже добре грають.

Я мав приємний досвід роботи з цією палітуркою моделі - https://github.com/theironcook/Backbone.ModelBinder . що дає розумні за замовчуванням ще чимало спеціального відображення вибору jquery атрибутів моделі для вхідних елементів.

Існує більш розширений список розширень / плагінів магістралей на github

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.