Apa yang mengikat dua arah?

173

Saya telah membaca banyak hal bahwa Backbone tidak melakukan dua cara mengikat tetapi saya tidak mengerti konsep ini.

Bisakah seseorang memberi saya contoh tentang bagaimana dua cara mengikat bekerja di basis kode MVC dan bagaimana tidak dengan Backbone?

Chris M.
sumber

Jawaban:

249

Pengikatan dua arah berarti:

  1. Ketika properti dalam model diperbarui, begitu pula UI.
  2. Ketika elemen UI diperbarui, perubahan akan disebarkan kembali ke model.

Backbone tidak memiliki implementasi "baked-in" # 2 (walaupun Anda tentu bisa melakukannya menggunakan pendengar acara). Kerangka kerja lain seperti Knockout melakukan pengikatan dua arah secara otomatis .


Di Backbone, Anda dapat dengan mudah mencapai # 1 dengan mengikat metode tampilan "render" ke acara "perubahan" modelnya. Untuk mencapai # 2, Anda juga perlu menambahkan pendengar perubahan ke elemen input, dan memanggil model.setpawang.

Inilah Fiddle dengan pengikatan dua arah yang diatur di Backbone.

McGarnagle
sumber
25
Jawabannya sangat jelas sekali setelah Anda melihatnya. Terima kasih banyak telah meluangkan waktu untuk memberikan jawaban dan contoh yang jelas.
Chris M
Dan dengan Firebase hadir ... penyatuan data 3 arah -> View, Model, Database. Hanya berpikir itu cukup rapi.
Levi Fuller
Ringkas dan pendek. +1
Karan_powered_by_RedBull
46

Pengikatan dua arah berarti bahwa setiap perubahan terkait data yang mempengaruhi model segera disebarkan ke tampilan yang sesuai, dan bahwa setiap perubahan yang dibuat dalam tampilan (misalnya) oleh pengguna) segera tercermin dalam model yang mendasarinya. . Ketika data aplikasi berubah, begitu pula UI, dan sebaliknya.

Ini adalah konsep yang sangat solid untuk membangun aplikasi web di atas, karena membuat abstraksi "Model" menjadi sumber data atom yang aman untuk digunakan di mana saja dalam aplikasi. Katakanlah, jika sebuah model, terikat pada tampilan, berubah, maka bagian UI yang cocok (tampilan) akan mencerminkan itu, apa pun yang terjadi . Dan bagian yang cocok dari UI (tampilan) dapat digunakan dengan aman sebagai sarana untuk mengumpulkan input / data pengguna, untuk menjaga data aplikasi tetap terbaru.

Implementasi pengikatan dua arah yang baik jelas harus membuat hubungan antara model dan beberapa tampilan sesederhana mungkin, dari sudut pandang pengembang.

Maka tidak benar untuk mengatakan bahwa Backbone tidak mendukung pengikatan dua arah: walaupun bukan fitur inti dari kerangka kerja, Backbone dapat dilakukan dengan cukup sederhana menggunakan Acara Backbone. Harganya beberapa baris kode eksplisit untuk kasus-kasus sederhana; dan bisa menjadi sangat berbahaya untuk binding yang lebih kompleks. Berikut ini adalah kasus sederhana (kode yang belum diuji, ditulis dengan cepat hanya untuk ilustrasi):

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}

Ini adalah pola yang cukup khas dalam aplikasi Backbone mentah. Seperti yang dapat dilihat, dibutuhkan sejumlah kode (cukup standar) yang layak.

AngularJS dan beberapa alternatif lain ( Ember , Knockout ...) menyediakan pengikatan dua arah sebagai fitur warga negara pertama. Mereka mengabstraksikan banyak kasus tepi di bawah beberapa DSL, dan melakukan yang terbaik untuk mengintegrasikan ikatan dua arah dalam ekosistem mereka. Contoh kita akan terlihat seperti ini dengan AngularJS (kode yang belum diuji, lihat di atas):

<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: ''}

Agak pendek!

Namun, ketahuilah bahwa beberapa ekstensi pengikat dua arah yang lengkap juga ada untuk Backbone juga (dalam urutan mentah, subyektif dari penurunan kompleksitas): Epoxy , Stickit , ModelBinder ...

Salah satu hal keren dengan Epoxy, misalnya, adalah memungkinkan Anda untuk mendeklarasikan binding Anda (atribut model <-> elemen DOM view) baik di dalam template (DOM), atau dalam implementasi view (JavaScript). Beberapa orang sangat tidak suka menambahkan "arahan" ke DOM / template (seperti atribut ng-* yang diperlukan oleh AngularJS, atau atribut data-binding Ember).

Mengambil Epoxy sebagai contoh, seseorang dapat mengolah aplikasi Backbone mentah menjadi sesuatu seperti ini (...):

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}

Secara keseluruhan, hampir semua kerangka kerja "mainstream" JS mendukung pengikatan dua arah. Beberapa dari mereka, seperti Backbone, memang membutuhkan beberapa pekerjaan ekstra untuk membuatnya bekerja dengan lancar , tetapi mereka adalah sama yang tidak menegakkan cara tertentu untuk melakukannya, untuk memulainya. Jadi ini benar-benar tentang keadaan pikiran Anda.

Juga, Anda mungkin tertarik pada Flux , arsitektur berbeda untuk aplikasi web yang mempromosikan pengikatan satu arah melalui pola melingkar. Ini didasarkan pada konsep rendering ulang yang cepat dan holistik dari komponen UI pada setiap perubahan data untuk memastikan kekompakan dan membuatnya lebih mudah untuk alasan tentang kode / aliran data. Dalam tren yang sama, Anda mungkin ingin memeriksa konsep MVI (Model-View-Intent), misalnya Cycle .

chikamichi
sumber
3
Banyak pengembang, terutama pengembang React / Flux tidak menganggap pengikatan dua arah sebagai pola aman untuk membangun aplikasi skala besar.
Andy
28

McGarnagle memiliki jawaban yang bagus, dan Anda pasti ingin menerimanya, tetapi saya pikir saya akan menyebutkan (karena Anda bertanya) bagaimana cara kerja penyatuan data.

Ini umumnya diimplementasikan dengan menembakkan peristiwa setiap kali ada perubahan pada data, yang kemudian menyebabkan pendengar (misalnya UI) diperbarui.

Penjilidan dua arah bekerja dengan melakukan ini dua kali, dengan sedikit kehati-hatian untuk memastikan bahwa Anda tidak terjebak dalam suatu peristiwa perulangan (di mana pembaruan dari peristiwa tersebut menyebabkan peristiwa lain dipecat).

Saya akan memberikan komentar ini, tapi sudah cukup lama ...

Jeff
sumber
2

Sebenarnya emberjsmendukung pengikatan dua arah, yang merupakan salah satu fitur paling kuat untuk kerangka MVC javascript. Anda dapat memeriksanya di tempat yang disebutkan bindingdalam panduan pengguna.

untuk emberjs, untuk membuat pengikatan dua arah adalah dengan membuat properti baru dengan string Binding di akhir, kemudian menetapkan lintasan dari lingkup global:

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

Perhatikan bahwa binding tidak segera diperbarui. Ember menunggu hingga semua kode aplikasi Anda selesai berjalan sebelum menyinkronkan perubahan, sehingga Anda dapat mengubah properti terikat sebanyak yang Anda inginkan tanpa khawatir tentang overhead sinkronisasi sinkronisasi ketika nilainya transien.

Semoga ini membantu dalam memperluas jawaban asli yang dipilih.

desain weia
sumber
1

Layak disebutkan bahwa ada banyak solusi berbeda yang menawarkan dua cara mengikat dan bermain dengan sangat baik.

Saya telah memiliki pengalaman yang menyenangkan dengan pengikat model ini - https://github.com/theironcook/Backbone.ModelBinder . yang memberikan default yang masuk akal namun banyak pemetaan pemilih jquery kustom atribut model ke elemen input.

Ada daftar ekstensi / plugin backbone yang lebih panjang di github

Daniel
sumber