2016-08-05 18 views
0

Neu zu knockout Ich versuche, ein POC für benutzerdefinierte Elemente aufzubauen.Benutzerdefinierte Element in foreach haben nicht erwartet, Modell in Knockout

Die Modelle sind einfach, ein MainModel enthält ein Array von LinkModel.

Ziel ist die Iteration durch das Array von Links, um für jedes LinkModel-Objekt ein benutzerdefiniertes Element "settings-view-link" anzuzeigen.

function LinkModel(params) { 
    var self = this; 
    self.name = ko.observable(params.name); 
} 

function MainModel() { 
    var self = this; 
    self.links = ko.observableArray([ 
     new LinkModel({ name: "link1"}), 
     new LinkModel({ name: "link2"}) 
    ]); 
}; 

$(function() { 
    //registration of the custom element 
    ko.components.register('settings-view-link', 
    { 
     viewModel: LinkModel, 
     template: "<div><strong data-bind='text: name'></strong></div>" 
    }); 
    ko.applyBindings(new MainModel()); 
}); 
<div> 
    <ul data-bind="foreach: links"> 
     <p data-bind="text: name"></p> <!-- handled correctly --> 
     <settings-view-link></settings-view-link> <!-- handled not the way I expect--> 
    </ul> 
</div> 

Was ich sehe, ist, dass, wenn in der benutzerdefinierten Element muss ich $ parent verwenden. damit meine Datenbindung wie erwartet funktioniert.

<div><strong data-bind='text: $parent.name'></strong></div> 
Mit

statt

<div><strong data-bind='text: name'></strong></div> 

macht den Namen meiner Links auf der Webseite erscheinen.

Ich erwartete, dass innerhalb der benutzerdefinierten Element behandelt es ein LinkModel-Objekt, aber es ist nicht, es ist irgendwie ein "Submodell". Kann jemand erklären, warum ich $ Eltern verwenden muss? Code ist falsch, aber warum? Ich erwarte wirklich ein LinkModel-Objekt in meinem benutzerdefinierten Element.

Vielen Dank

Antwort

1

Da die benutzerdefinierte Komponente gibt eine viewModel Option, Knockout wird eine neue Instanz dieses Ansichtsmodell für Sie erstellen. Sie können die Eigenschaft weglassen und knockout wird die Komponente an die angegebenen Parameter binden:

Komponenten haben in der Regel Viewmodels, aber sie müssen nicht unbedingt. Eine Komponente kann nur eine Vorlage angeben. In diesem Fall, zu dem das Objekt nach Ansicht der Komponente gebunden ist, die params Objekt, das Sie an die Komponente übergeben Bindung

Quelle: http://knockoutjs.com/documentation/component-binding.html#note-template-only-components

Dieses Beispiel könnte besser erklären, was ich meine. Die erste Komponente gibt eine Viewmodel-Funktion an, die instanziiert und an die Komponenteninstanz gebunden wird.

Die zweite Komponente übergibt $data als Parameter und funktioniert grundsätzlich als Vorlage. Sie benötigen möglicherweise nur die Vorlagenbindung, wenn Sie nicht automatisch neue Ansichtsmodelle erstellen möchten.

var instanceCounter = 0; 
 

 
var ViewModel = function() { 
 
    this.nr = instanceCounter++; 
 
} 
 

 
ko.components.register('testComponent1', { 
 
    viewModel: ViewModel, 
 
    template: '<div data-bind="text: nr"></div>' 
 
}); 
 

 
ko.components.register('testComponent2', { 
 
    template: '<div data-bind="text: nr"></div>' 
 
}); 
 

 

 
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 

 

 
<section> 
 
    <h2>New instance for each component</h2> 
 
    <div data-bind='component: { 
 
    name: "testComponent1" 
 
}'></div> 
 
    <div data-bind='component: { 
 
    name: "testComponent1" 
 
}'></div> 
 
    <div data-bind='component: { 
 
    name: "testComponent1" 
 
}'></div> 
 
</section> 
 

 
<section> 
 
    <h2>Same instance for each component</h2> 
 
    <div data-bind='component: { 
 
    name: "testComponent2", 
 
    params: $data 
 
}'></div> 
 
    <div data-bind='component: { 
 
    name: "testComponent2", 
 
    params: $data 
 
}'></div> 
 
    <div data-bind='component: { 
 
    name: "testComponent2", 
 
    params: $data 
 
}'></div> 
 
</section>

+0

Vielen Dank es funktioniert! – Seamus