Wie werden If-Else-Strukturen in datengebundenen Ansichten erstellt?

94

Ich verwende dieses Idiom ständig in KO-basierten HTML-Vorlagen:

<!-- ko if: isEdit -->
<td><input type="text" name="email" data-bind="value: email" /></td>
<!-- /ko -->
<!-- ko ifnot: isEdit -->
<td data-bind="text: email"></td>
<!-- /ko -->

Gibt es eine bessere / sauberere Möglichkeit, Bedingungen in KO zu erfüllen, oder gibt es eine bessere Ansatz als nur die Verwendung traditioneller if-else-Konstrukte?

Außerdem möchte ich nur darauf hinweisen, dass einige Versionen von Internet Explorer (IE 8/9) das obige Beispiel nicht korrekt analysieren. Weitere Informationen finden Sie in dieser SO-Frage . Die kurze Zusammenfassung lautet: Verwenden Sie keine Kommentare (virtuelle Bindungen) in Tabellen-Tags, um den IE zu unterstützen. Verwenden Sie tbodystattdessen:

<tbody data-bind="if: display"><tr><td>hello</td></tr></tbody>
Jensen Ching
quelle
Jeder, der sich das ansieht, möchte vielleicht github.com/knockout/knockout/issues/962
Brian M. Hunt

Antworten:

63

Es gibt verschiedene Möglichkeiten, wie Sie mit dieser Art von Code umgehen können.

  • mit einer if / ifnot-Kombination wie Sie es jetzt sind. Dies funktioniert gut und ist nicht sehr ausführlich.

  • Die Switch / Case-Bindung von Michael Best ( https://github.com/mbest/knockout-switch-case ) ist sehr flexibel und ermöglicht es Ihnen, diese und kompliziertere (mehr Zustände als wahr / falsch) einfach zu handhaben.

  • Eine weitere Option ist die Verwendung dynamischer Vorlagen. Sie würden einen Bereich an eine oder mehrere Vorlagen binden, wobei der Vorlagenname basierend auf einem Observable verwendet wird. Hier ist ein Beitrag, den ich vor einiger Zeit zu diesem Thema geschrieben habe: http://www.knockmeout.net/2011/03/quick-tip-dynamically-changing.html . In Ihrem Szenario könnte es so aussehen:

<td data-bind="template: $root.getCellTemplate"></td>

<script id="cellEditTmpl" type="text/html">
    <input type="text" name="email" data-bind="value: email" />
</script>

<script id="cellTmpl" type="text/html">
    <span data-bind="text: email"></span>
</script>

Die getCellTemplateFunktion könnte überall leben, würde jedoch das Element ($ data) als erstes Argument erhalten und den Namen der zu verwendenden Vorlage zurückgeben.

RP Niemeyer
quelle
seltsam, mein HTML wird nicht angezeigt. Ich habe auch gerade bemerkt, dass Michael so ziemlich die gleiche Antwort gab.
RP Niemeyer
Vielen Dank für eine umfassende Liste von Optionen. Ich denke, mein ursprünglicher Codestil funktioniert für einfache Fälle. Ich werde die anderen Optionen prüfen, wenn es nötig ist.
Jensen Ching
Gibt es eine Möglichkeit, die Vorlage noch weiter anzupassen, z. B. "template: data, proppertyName: 'email'" und in der Vorlage data-bind = "text: $ data [propertyName]".
Onur Topal
@OnurTOPAL - Ja, solange Sie eine Variable haben propertyName, können Sie den Vorlagennamen dynamisch bestimmen.
RP Niemeyer
44

Ein Ansatz besteht darin, benannte Vorlagen zu verwenden (die das Übergeben von Argumenten unterstützen können):

<!-- ko template: isEdit() ? 'emailEdit' : 'emailDisplay' --><!-- /ko -->
<script id="emailEdit" type="text/html">
    <td><input type="text" name="email" data-bind="value: email" /></td>
</script>
<script id="emailDisplay" type="text/html">
    <td data-bind="text: email"></td>
</script>

Eine andere Option ist die Verwendung meines Switch / Case-Plugins , das folgendermaßen funktionieren würde:

<!-- ko switch -->
    <!-- ko case: isEdit -->
        <td><input type="text" name="email" data-bind="value: email" /></td>
    <!-- /ko -->
    <!-- ko case: $else -->
        <td data-bind="text: email"></td>
    <!-- /ko -->
<!-- /ko -->
Michael Best
quelle
Vielen Dank. Ich werde das Switch / Case-Plugin im Hinterkopf behalten, wenn es nötig ist.
Jensen Ching
2
Schönes Plugin, das du da hast! Ich werde diesen auf jeden Fall verwenden.
Kukks
Benannte Vorlagen funktionieren hervorragend und unterstützen, wenn elseif elseif else-Szenarien durch Verschachtelung des terniären Operators.
4

Um eine Neuberechnung der Knockout-Bindung bei Verwendung der Kombination von if: / ifnot: zu vermeiden, können Sie diese in Verbindung mit der Konstruktion 'with:' verwenden

    <!-- ko with: $data.DoSomePerformanceCriticalWork($data.SomeParameter()) -->
        <!-- ko if: $data.Condition() -->
           ... some markup ...
        <!-- /ko -->
        <!-- ko ifnot: $data.Condition() -->
           ... some markup ...
        <!-- /ko -->
    <!-- /ko -->
Dmitry Komin
quelle
1

Es gibt jetzt auch die knockout-elseBindung / das Plugin (das ich geschrieben habe, um dieses Problem zu beheben).

Brian M. Hunt
quelle