İki yönlü bağlanma nedir?


173

Omurga'nın iki yönlü bağlanma yapmadığı birçok şey okudum ama bu kavramı tam olarak anlamıyorum.

Birisi bana bir MVC kod tabanında iki yönlü bağlamanın nasıl çalıştığına ve Omurga ile nasıl çalışmadığına bir örnek verebilir mi?

Yanıtlar:


249

İki yönlü ciltleme şu anlama gelir:

  1. Modeldeki özellikler güncellendiğinde, kullanıcı arayüzü de güncellenir.
  2. Kullanıcı arabirimi öğeleri güncellendiğinde, değişiklikler modele geri yayılır.

Omurga # 2'nin "pişmiş" bir uygulamasına sahip değildir (olay dinleyicilerini kullanarak kesinlikle yapabilirsiniz). Nakavt gibi diğer çerçeveler otomatik olarak iki yönlü ciltleme yapar .


Omurgada, bir görünümün "render" yöntemini modelinin "change" etkinliğine bağlayarak # 1'e kolayca ulaşabilirsiniz. # 2'ye ulaşmak için, giriş öğesine bir değişiklik dinleyicisi eklemeniz model.setve işleyiciyi çağırmanız gerekir .

İşte Omurgaya iki yönlü bağlanan bir Keman .


25
Cevabı gördüğünüzde çok acı veriyor. Açık bir cevap ve örnek vermek için zaman ayırdığınız için çok teşekkür ederim.
Chris M

Ve Firebase ile geliyor ... 3 yönlü veri bağlama -> Görünüm, Model, Veritabanı. Sadece çok temiz olduğunu düşündüm.
Levi Fuller

Kısa ve öz. +1
Karan_powered_by_RedBull

46

İki yönlü ciltleme, modeli etkileyen herhangi bir veriyle ilgili değişikliğin hemen eşleşen görünümlere yayıldığı ve görünümlerde (örneğin kullanıcı tarafından) yapılan değişikliklerin hemen altta yatan modele yansıtıldığı anlamına gelir . Uygulama verileri değiştiğinde, kullanıcı arayüzü de tersine değişir.

Bu, "Model" soyutlamasını uygulamanın her yerinde kullanmak için güvenli, atomik bir veri kaynağı haline getirdiğinden, bunun üzerine bir web uygulaması oluşturmak için çok sağlam bir kavramdır. Diyelim ki, bir görünüme bağlı bir model değişirse, o zaman eşleşen UI parçası (görünüm) ne olursa olsun bunu yansıtacaktır . Ve eşleşen kullanıcı arabirimi parçası (görünüm), uygulama verilerini güncel tutmak için kullanıcı girişlerini / verilerini toplama aracı olarak güvenle kullanılabilir.

İyi bir iki yönlü bağlayıcı uygulama, model ile bazı bakış açıları arasındaki bu bağlantıyı, geliştirici bakış açısından mümkün olduğunca basit hale getirmelidir.

O zaman Omurga'nın iki yönlü bağlamayı desteklemediğini söylemek tamamen doğru değildir : çerçevenin temel bir özelliği olmasa da, Omurga Olayları kullanılarak oldukça basit bir şekilde gerçekleştirilebilir. Basit durumlar için birkaç açık kod satırına mal olur; ve daha karmaşık ciltlemeler için oldukça tehlikeli olabilir. İşte basit bir durum (sadece illüstrasyon uğruna anında yazılmış test edilmemiş kod):

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}

Bu, ham bir Omurga uygulamasında oldukça tipik bir modeldir. Gördüğünüz gibi, iyi bir miktar (oldukça standart) kod gerektirir.

AngularJS ve diğer bazı alternatifler ( Ember , Knockout …), birinci vatandaş özelliği olarak iki yönlü bağlanma sağlar. Bazı DSL'lerde birçok kenar durumu soyutlar ve ekosistemlerine iki yönlü bağlamayı entegre etmek için ellerinden geleni yaparlar. Örneğimiz AngularJS (test edilmemiş kod, yukarıya bakın) ile şöyle görünecektir:

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

Oldukça kısa!

Ama bazı unutmayın tam teşekküllü iki yönlü bağlama uzantıları mevcut olamayacağı (karmaşıklığını azalan ham, sübjektif sırayla) Omurgası yanı: Epoksi , StickIt , ModelBinder ...

Örneğin, Epoksi ile harika bir şey, şablonlarınızda (DOM) veya görünüm uygulamasında (JavaScript) bağlarınızı (model nitelikleri <-> görünümün DOM öğesi) bildirmenize izin vermesidir. Bazı insanlar DOM / şablona "yönerge" eklemekten (AngularJS için gerekli olan ng- * nitelikleri veya Ember'in veri bağlama nitelikleri) kesinlikle beğenmezler.

Epoksi örnek olarak, ham Omurga uygulamasını böyle bir şeye yeniden çalıştırabilirsiniz (…):

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}

Sonuçta, hemen hemen tüm "ana akım" JS çerçeveleri iki yönlü bağlamayı destekler. Bazıları, Omurga gibi, düzgün çalışabilmesi için fazladan çalışmaya ihtiyaç duyarlar , ancak başlangıçta bunu yapmak için belirli bir yolu zorlamayanlar aynıdır. Yani bu gerçekten sizin ruh halinizle ilgilidir.

Ayrıca, dairesel uygulamalar yoluyla tek yönlü bağlanmayı destekleyen web uygulamaları için farklı bir mimari olan Flux ile ilgilenebilirsiniz . Uyumluluğu sağlamak ve kod / veri akışı hakkında akıl yürütmeyi kolaylaştırmak için UI bileşenlerinin herhangi bir veri değişikliği üzerine hızlı, bütünsel olarak yeniden oluşturulması kavramına dayanır. Aynı trendde, MVI (Model-View-Intent) kavramını, örneğin Döngüyü kontrol etmek isteyebilirsiniz .


3
Birçok geliştirici, özellikle React / Flux geliştiricileri iki yönlü bağlamayı büyük ölçekli uygulamalar oluşturmak için güvenli bir model olarak görmüyor.
Andy

28

McGarnagle'ın harika bir cevabı var ve onu kabul etmek isteyeceksiniz, ancak veritabanının nasıl çalıştığını (siz sorduğunuzdan beri) anlatacağımı düşündüm.

Genellikle verilerde her değişiklik yapıldığında olayları tetikleyerek uygulanır ve bu da dinleyicilerin (örn. UI) güncellenmesine neden olur.

İki yönlü bağlama, bir olay döngüsünde sıkışıp kalmamanızı sağlamak için biraz özen göstererek bunu iki kez yaparak çalışır (olaydan gelen güncelleme başka bir olayın tetiklenmesine neden olur).

Bunu bir yoruma ekleyecektim, ama oldukça uzundu ...


2

Aslında emberjsbir javascript MVC çerçevesi için en güçlü özelliklerden biri olan iki yönlü bağlamayı destekler. bindingKullanım kılavuzunda bahsettiği yeri kontrol edebilirsiniz .

emberjs için, iki yönlü ciltleme oluşturmak, sonunda Binding dizesiyle yeni bir özellik oluşturmak ve ardından global kapsamdan bir yol belirtmektir:

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

Bağlamaların hemen güncellenmediğini unutmayın. Ember, değişiklikleri senkronize etmeden önce tüm uygulama kodunuzun çalışmasının bitmesini bekler, böylece değerler geçici olduğunda bağlamaların ek yükü hakkında endişelenmeden bağlı bir özelliği istediğiniz kadar değiştirebilirsiniz.

Umarım seçilen orijinal cevabın genişlemesine yardımcı olur.


1

İki yönlü bağlanma sunan ve gerçekten güzel oynayan birçok farklı çözüm olduğunu belirtmek gerekir.

Bu model bağlayıcı ile hoş bir deneyim yaşadım - https://github.com/theironcook/Backbone.ModelBinder . bu da mantıklı varsayılan değerler sunarken, model niteliklerinin giriş öğelerine çok sayıda özel jquery seçici eşlemesi sağlar.

Github'da daha geniş bir omurga uzantıları / eklentileri listesi var

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.