KnockOutJS - Tek bir Görünümde Birden Çok ViewModel


201

Uygulamamın her bir Görünümü tek bir ViewModel ile işleyemeyecek kadar büyük hale geldiğini düşünüyorum.

Bu yüzden birden fazla ViewModel oluşturmanın ve hepsini tek bir Görünüm'e yüklemenin ne kadar zor olacağını merak ediyorum. Ayrıca X ViewModel verilerini Y ViewModel verilerine aktarabilmem gerektiğini unutmayın, böylece bireysel ViewModels birbirleriyle iletişim kurabilmeli veya en azından birbirlerinin farkında olmalıdır.

Örneğin, bir <select>açılır menü var, bu seçim açılır menüde seçilen öğenin kimliğini <select>ayrı bir ViewModel içinde başka bir Ajax çağrısına geçirmek için izin veren bir durum vardır ....

Tek bir Görünümde çok sayıda ViewModel ile ilgili herhangi bir puan takdir :)


12
Bu soruya gelenler için lütfen kabul edilen yanıtı kaydırın. Nakavt artık birden çok bağlama bağlamını destekliyor . Bir deve gerek yok masterVM.
Carrie Kendall

Yanıtlar:


150

Hepsinin aynı sayfada olması gerekiyorsa, bunu yapmanın kolay bir yolu, diğer görünüm modellerinin bir dizisini (veya özellik listesini) içeren bir ana görünüm modeline sahip olmaktır.

masterVM = {
    vmA : new VmA(),
    vmB : new VmB(),
    vmC : new VmC(),
}

Ardından masterVM, sayfanın kendisi için gerekirse başka özelliklere de sahip olabilirsiniz. Görünüm modelleri arasındaki iletişim, bu durumda geçiş yapabileceğiniz masterVMveya $parent/ $rootin bağlamaları veya diğer bazı özel seçenekleri kullanabileceğiniz için zor olmaz .


2
Yani şöyle bir şey yapabilir miyim: data-bind = "text: masterVM.vmA", varsayalım DOM öğesi ile ko.applyBindings hala kullanabilirsiniz. Bunun da yapabileceğim anlamına geleceğini varsayın: data-bind = "$ parent.masterVm"?
CLiown

12
@CLiown Ciltlemeyi kullanabilirsiniz with:, bu yüzden kendinizi tekrar etmeyeceksiniz
AlfeG

4
@CLiown Evet, masterVM'ye bağlıysanız bunu yapabilirsiniz. Alt görünüm modellerine daldığınızda nokta sözdizimini önlemeye yardımcı olması için "with" bağlamasını da kullanabilirsiniz.
John Papa

1
Bu yaklaşım çok kısıtlayıcı olduğunu düşünüyorum ... Şimdi benim durumumda ASP.Net MVC4 kullanıyorum, kendi ViewModels ve kısmi / İçerik bölümleri olan kısmi görünümler olacağı için bu yardımcı olmaz ve koşullu oluşturma nedeniyle bu yaklaşımı kullanmak gerçekten zor olacaktır.
bhuvin

1
@bhuvin <! - ko stopBinding: true -> kullanarak çoklu görünüm modelleri ve kısmi görünüm bölümlerinde size yardımcı olacaktır. Daha fazla bilgi için knockmeout.net/2012/05/quick-tip-skip-binding.html adresine bakın .
Micaël Félix

285

Nakavt artık çoklu model bağlanmasını destekliyor. ko.applyBindings()Bağlayıcı aktif olacak olan elemanının ve kökenini - yöntem, isteğe bağlı bir parametre alır.

Örneğin:

ko.applyBindings(myViewModel, document.getElementById('someElementId'))

Bu, etkinleştirme kimliğine someElementIdve alt öğelerine sahip öğeyle sınırlandırılır .

Daha fazla ayrıntı için belgelere bakın.


72
Bir jQuery seçici kullanmak istiyorsanız, aşağıdaki gibi [0]gerçek bir DOM öğesi (jQuery nesnesi yerine) belirtmek için eklemek istersiniz:ko.applyBindings(myViewModel, $('#someElementId')[0])
MrBoJangles

3
Bu kabul edilen cevap olmalı. Halihazırda kabul edilen yanıtın sahip olduğu gibi bir ana nesne kullanabilir ve ardından ayrı ayrı görünüm modellerini sayfadaki uygun öğelerine bağlayabilirsiniz. Bu performanstan tasarruf sağlar ve veri bağlama için gereken kapsamı sınırlar.
Kevin Heidt

ViewModels'i bu yaklaşımla birbirleriyle iletmek mümkün mü? yani TaskVM ve NoteVM var. Görev Notlar içerebilir. Bu nedenle TaskVM'mde türünün TaskVM olan bir obsableArray olması gerekir. Böyle bir vakaya örnek verebilir misiniz?
ahmet

Yeni bir soruda VM'ler arasındaki iletişimi sormak muhtemelen en iyisidir.
Richard Nalezynski

21

Bu, tek bir görünümde çok sayıda ViewModel içeren çok büyük bir projeyi tamamladıktan sonra cevabım.

Html Görüntüle

    <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body>
    <div id="container1">
        <ul>
            <li >Container1 item</li>
            <!-- ko foreach: myItems -->
            <li>Item <span data-bind="text: $data"></span></li>
            <!-- /ko -->
        </ul>
    </div>

    <div id="container2">
        <ul>
            <li >Container2 item</li>
            <!-- ko foreach: myItems -->
                <li>Item <span data-bind="text: $data"></span></li>
            <!-- /ko -->
        </ul>
    </div>

    <script src="js/jquery-1.11.1.js"></script>
    <script src="js/knockout-3.0.0.js"></script>
    <script src="js/DataFunction.js"></script>
    <script src="js/Container1ViewModel.js"></script>
    <script src="js/Container2ViewModel.js"></script>

</body>
</html>

Bu görünüm için iki ayrı javascript dosyasında id = container1 ve id = container2 için 2 görünüm modeli oluşturuyorum.

Container1ViewModel.js

function Container1ViewModel()
{
    var self = this;
    self.myItems = ko.observableArray();
    self.myItems.push("ABC");
    self.myItems.push("CDE");

} 

Container2ViewModel.js

function Container2ViewModel() {
    var self = this;
    self.myItems = ko.observableArray();
    self.myItems.push("XYZ");
    self.myItems.push("PQR");

}

Sonra bu 2 görüntü modeli sonra DataFunction.js ayrı görünüm modelleri olarak kayıt

var container1VM;
var container2VM;

$(document).ready(function() {

    if ($.isEmptyObject(container1VM)) {
        container1VM = new Container1ViewModel();
        ko.applyBindings(container1VM, document.getElementById("container1"));
    }

    if ($.isEmptyObject(container2VM)) {
        container2VM = new Container2ViewModel();
        ko.applyBindings(container2VM, document.getElementById("container2"));
    }
});

Bunun gibi, ayrı div'ler için istediğiniz sayıda görünüm modeli ekleyebilirsiniz. Ancak, kayıtlı div içindeki bir div için ayrı görünüm modeli oluşturmadığınızdan emin olun.


DOM'un ayrı unsurları olmak yerine bir çeşit viewmodel yapmak mümkün mü?
UserEsp

4

Knockout JS için MultiModels eklentisini kontrol edin - https://github.com/sergun/Knockout-MultiModels


6
Bunun sadece ko.applyBindings (viewModel, document.getElementById ("divName")) üzerindeki avantajı nedir? Sadece sözdizimsel şeker değil mi?
Paolo del Mundo

1
@Paolo del Mundo LiveQuery eklentisine de bağımlılık ekler.
Lars Gyrup Brink Nielsen

@PaolodelMundo eklentinin amacı bir dizi görünüm modelini dekalratif bir şekilde kullanabilmektir
Sergey Zwezdin

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.