Wie wendet Magento 2 KnockoutJS-Bindungen an?


19

Nach einer sehr flüchtigen Lektüre der KnockoutJS-Dokumentation sieht das Initialisieren einer sehr einfachen Knockout-Ansicht folgendermaßen aus

// This is a simple *viewmodel* - JavaScript that defines the data and behavior of your UI
function AppViewModel() {
    this.firstName = "Bert";
    this.lastName = "Bertington";
}

// Activates knockout.js
ko.applyBindings(new AppViewModel());

dh - Sie erstellen eine JavaScript-Funktion, die als Objektkonstruktor verwendet werden soll, instanziieren ein Objekt daraus und übergeben dieses Objekt dann an die ko.applyBindingsMethode des globalen Knockout-Objekts ( ko).

Wenn Sie jedoch in Magento 2 eine Backend-Seite mit einer Raster-Benutzeroberfläche laden, initialisiert Magento das js/core/app.jsRequireJS-Modul

/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
define([
    './renderer/types',
    './renderer/layout',
    'Magento_Ui/js/lib/ko/initialize'
], function (types, layout) {
    'use strict';

    return function (data) {
        types.set(data.types);
        layout(data.components);
    };
});

Dieses Modul lädt wiederum das Magento_Ui/js/lib/ko/initializeModul, das Magentos Verwendung von KnockoutJS zu initialisieren scheint . Betrachten Sie jedoch die Quelle des Initialisierungsmoduls.

define([
    'ko',
    './template/engine',
    'knockoutjs/knockout-repeat',
    'knockoutjs/knockout-fast-foreach',
    'knockoutjs/knockout-es5',
    './bind/scope',
    './bind/staticChecked',
    './bind/datepicker',
    './bind/outer_click',
    './bind/keyboard',
    './bind/optgroup',
    './bind/fadeVisible',
    './bind/mage-init',
    './bind/after-render',
    './bind/i18n',
    './bind/collapsible',
    './bind/autoselect',
    './extender/observable_array',
    './extender/bound-nodes'
], function (ko, templateEngine) {
    'use strict';

    ko.setTemplateEngine(templateEngine);
    ko.applyBindings();
});

Sie sehen, dass Magento das ko.applyBindings();Objekt ohne Ansichtsobjekt nennt . Das ergibt keinen Sinn und ich bin mir nicht sicher, ob es sich um mein begrenztes Verständnis von Knockout handelt oder ob Magento hier etwas Besonderes macht.

Wendet Magento hier tatsächlich Knockout-Bindungen an? Oder passiert das woanders? Oder tut Magento etwas Schwieriges, um Knockout-Code abzufangen und woanders zu verarbeiten?

Antworten:


38

In der Magento_Ui/js/lib/ko/initializeBibliothek initialisiert Magento seine Knockout-Instanz. Magento weist kein ViewModel zu, wenn es Bindungen anwendet.

Der fehlende Schlüssel ist hier die benutzerdefinierte KnockoutJS-Bindung mit dem Namen scope.

Wenn die Knockout-Instanz von Magento auf eine solche scope:Bindung stößt

<li class="greet welcome" data-bind="scope: 'customer'">
    <span data-bind="text: customer().fullname ? $t('Welcome, %1!').replace('%1', customer().fullname) : 'Default welcome msg!'"></span>
</li>

Es nimmt den Wert dieser Bindung (benannt customer) und verwendet ihn zum Laden und Anwenden eines ViewModel für die inneren Knoten von uiRegistry. Sie können die für einen bestimmten Bereich gebundenen Daten mit einem einfachen KnockoutJS- preDebugging debuggen

<div data-bind="scope: 'someScope'">
    <pre data-bind="text: ko.toJSON($data, null, 2)"></pre>            
</div>

Das uiRegistryist ein einfaches Wörterbuch ähnliches Objekt, in dem implementierten Magento_Ui/js/lib/registry/registryRequireJS Modul.

vendor/magento/module-ui/view/base/requirejs-config.js
17:            uiRegistry:     'Magento_Ui/js/lib/registry/registry',

Objekte werden über die so aussehenden Javascript-Bits in die Registrierung gestellt

<script type="text/x-magento-init">
{
    "*": {
        "Magento_Ui/js/core/app": {
            "components": {
                "customer": {
                    "component": "Magento_Customer/js/view/customer",
                    "extra_data_1":"some_value",
                    "more_extra":"some_other_value",
                }
            }
        }
    }
}
</script>

Das Programm im Magento_Ui/js/core/appModul prüft den componentsSchlüssel des übergebenen Objekts und für jedes Unterobjekt

  1. Ruft das vom angegebenen RequireJSModul zurückgegebene Objekt vom componentkey ( Magento_Customer/js/view/customer) ab.

  2. Verwenden Sie dieses Objekt, um ein neues Javascript- Objekt zu instanziieren (siehe unten).

  3. Weisen Sie demselben Objekt zusätzliche Datenschlüssel zu

  4. Fügen Sie dasselbe Objekt uiRegistrymit dem Schlüssel des ursprünglichen Objekts ( customeroben) zum hinzu.

Wenn Sie sich nicht sicher sind, wie das x-magento-initSkript funktioniert, habe ich hier einen Artikel darüber geschrieben .

In dieser Antwort wird der app.jsProzess eingehender untersucht .

Die Implementierung der Scope-Bindung wird hier definiert

vendor/magento//module-ui/view/base/web/js/lib/ko/bind/scope.js

Alan, es ist eine großartige Antwort! Danke für die Information. In Bezug auf Aufzählungspunkt 3, wie zusätzliche Datenschlüssel zum neu instanziierten Objekt hinzugefügt werden. Wird es Eigenschaften oder etwas anderes sein?
Timik
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.