5

Gibt es eine Möglichkeit, ein Knockout component zu zu konfigurieren, ersetzen Sie das Containerelement, anstatt seinen Inhalt innerhalb des Containerelements zu verschachteln?Ersetzen des Containerelements bei Verwendung der Knockout-Komponente

Zum Beispiel, wenn ich eine eigene Komponente als my-custom-element mit der folgenden Vorlage registriert hat:

<tr> 
    <p>Hello world!</p> 
</tr> 

Ist es möglich, die Komponente wie folgt zu verwenden:

<table> 
    <tbody> 
     <my-custom-element></my-custom-element> 
    </tbody> 
</table> 

Und hat das Endprodukt dies:

<table> 
    <tbody> 
     <tr> 
      <p>Hello world!</p> 
     </tr> 
    </tbody> 
</table> 

Statt dessen: (die Art und Weise Knockout r Enders Komponenten standardmäßig)

<table> 
    <tbody> 
     <my-custom-element> 
      <tr> 
       <p>Hello world!</p> 
      </tr> 
     </my-custom-element> 
    </tbody> 
</table> 

Based on the answer to this question, so scheint es, dass diese Funktionalität in den Template-Engine eingebaut, die auch ich gehe davon verwendet wird, wenn die Komponente Vorlagen machen.

Gibt es eine Möglichkeit anzugeben, dass eine Komponente mit einem renderMode von replaceNode gerendert werden soll?

Ich bin mir bewusst, die „virtuelles Element“ Syntax, die in einem HTML-Kommentar definierten Komponenten ermöglicht:

<table> 
    <tbody> 
     <!--ko component { name: 'my-custom-element' }--><!--/ko--> 
    </tbody> 
</table> 

aber ich wirklich diese Syntax nicht mögen - real das Schreiben von Code innerhalb ein Kommentar wie ein fühlt schmutziger, schmutziger Hack.

+1

Es klingt wie [Rendern einer benannten Vorlage] (http://knockoutjs.com/documentation/template-binding.html) ist das, was Sie suchen. Web-Komponente ist im Allgemeinen ein DOM-Knoten, der seine Kinder überschaut. Es soll nicht ersetzt werden, da das Konzept selbst in einem solchen Fall ruiniert ist. – mudasobwa

Antwort

4

stelle ich mir das Fehlen dieser Option als solches verteidigt werden kann, die Art der Bibliothek unter Berücksichtigung (dort, ich sagte es), und das Team Philosophie des Entwicklers:

Knockout ist eine Bibliothek und im Gegensatz zu anderen MVC es zwingt Sie nicht, eine Framework-definierte Methode zu verwenden, um Ihre Anwendung zu strukturieren. Wenn Sie die Template-Engine in Knockout im Vergleich zu fast allen anderen JS-Templating-Engines (in Angular, Unterstreichung, Schnurrbart, etc.) betrachten, erscheint Knockout als einziges, das natives HTML5-Rendering nicht "modt". Alle anderen verwenden ein benutzerdefiniertes Tag, sei es <% %> oder {{ }}, die einen kleinen JS-Parser benötigt, um die Tags in etwas Sinnvolles umzuwandeln (jetzt hat KO auch ein Knockout punches-Plugin, das die Tags im Schnurrbart-Stil enthält, und KO tut 'sin' a) kleines bisschen mit <!-- ko --> Kommentare). KO verwendet stattdessen HTML 5 benutzerdefinierte Elemente, Kommentar- und Attribut-Tags, vollständig "Vanille".
Zum Beispiel wird der JS/DOM-Typ von "Objekt (und Real Life?) Hierarchie" verwendet: nur Eltern können jemals Power auf ihre Kinder ausüben, und so das gebundene Element wird nicht ersetzt, aber vergrößert mit Kindern.Zur Veranschaulichung:

// we cannot do this in JS 
document.getElementById('elem').remove(); //implied .remove(self) 
// instead we do this 
var elem = document.getElementById('elem'); 
container = elem.parentNode.removeChild(elem); 

Nachfolgend wird die bevorzugte Art der Datenbindung mit KO, veranschaulicht gut durch die foreach Bindung ist:

<div data-bind="foreach: myList"> 
    <span data-bind="text: $data"></span> 
</div> 

Die vorherige Schnipsel ist, um eine HTML-Darstellung eines JS Array, die Hierarchie ist wieder sichtbar:

var myArr = [1,2,3,4,5]; 
// we cannot do the following without reference to the array index, 
// which is not held by the object itself,  
// but a meta-property getting meaning relative to the parent 
myArr[0].splice(0,1); //remove 

Dies führt dazu, dass Ihre HTML-Ansicht ein perfekter ist ct-Replikation Ihrer JS-Daten (und es wäre interessant zu sehen, wie jemand ein Tool erstellt, das die Einrückungsstufen der Datenbindung anzeigt (mit with und foreach) in einem HTML-Dokument. In einigen Fällen benötigen Sie jedoch Kommentartags, um das Layout Ihres HTML-Codes oder Ihre CSS-Regeln (Verschachtelung) nicht zu unterbrechen, z. B. eine Nur-Text-Komponente (i18n), die zwischen Text eingefügt werden soll Knoten:

<p>Some predefined text with 
<!-- ko text: 'some variable text' --><!-- /ko --> 
and more predefined text</p> 

Oder, wenn Sie Raum nicht ein leeres Element wollen aufzunehmen, wenn

<!-- ko if: !hidden() --><div id="myToggleableDiv"></div><!-- /ko --> 

versteckt und dann gibt es custom tags, die standardisierte und eine Hölle von viel klarer sind ; aber leider noch nicht 100% fertig. Wählen Sie data-bind zuerst, <!-- ko --> zweite und <custom> dritte (wäre höher, wenn vollständig implementiert). So sehe ich es jedenfalls. Wie für Ihren speziellen Fall, wenn Ihre Komponente eine Liste Modell hält, könnten Sie tun:

<table data-bind="{component: {name: 'custom', params {..}}"></table> 

und schließen die tbody in Ihrer VM, sonst wäre es ein listitem Modell ist, können Sie entweder eine der drei verwenden ' Syntaxen, zB die Kommentarsyntax

<table> 
    <tbody data-bind="foreach: mylist"> 
    <!-- ko component: {name: 'custom', params: $data} --><!-- /ko --> 
    </tbody> 
</table> 

Oder Ihre Komponente vollständig von der Pflicht zur Entkopplung in einer bestimmten übergeordneten (Tabelle) verschachtelt ist, die Einhaltung der SOC principle, zB:

<table> 
    <tbody data-bind="foreach: mylist"> 
    <tr data-bind="foreach: properties"> 
     <td data-bind="component: {name: 'custom', params: $data}></td> 
    </tr> 
    </tbody> 
</table> 

oder mit einem benutzerdefinierten Tag:

<table> 
    <tbody data-bind="foreach: mylist"> 
    <tr data-bind="foreach: properties"> 
     <td><custom params= "{data: myData"></custom></td> 
    </tr> 
    </tbody> 
</table> 

in dieser Reihenfolge der Präferenz ..

2

Gute Nachrichten! In Knockout 3.3.0 haben sie gerade das Konzept Passing markup into components eingeführt. Dies geschieht mithilfe der Vorlage $componentTemplateNodes in Ihrer Komponente.

aus dem verknüpften Beispiel:

<template id="my-special-list-template"> 
    <h3>Here is a special list</h3> 

    <ul data-bind="foreach: { data: myItems, as: 'myItem' }"> 
     <li> 
      <h4>Here is another one of my special items</h4> 
      <!-- ko template: { nodes: $componentTemplateNodes, data: myItem } --><!-- /ko --> 
     </li> 
    </ul> 
</template> 

<my-special-list params="items: someArrayOfPeople"> 
    <!-- Look, I'm putting markup inside a custom element --> 
    The person <em data-bind="text: name"></em> 
    is <em data-bind="text: age"></em> years old. 
</my-special-list>