Magento 2はKnockoutJSバインディングをどのように適用しますか


19

KnockoutJSドキュメントを非常に大まかに読むと、非常に基本的なKnockoutビューの初期化は次のようになります。

// 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());

つまり、オブジェクトコンストラクターとして使用するjavascript関数を作成し、そこからオブジェクトをインスタンス化し、そのオブジェクトをko.applyBindingsグローバルノックアウトオブジェクトのメソッドに渡します(ko

ただし、Magento 2では、グリッドUIでバックエンドページをロードすると、Magentoはjs/core/app.jsRequireJSモジュールを初期化します

/**
 * 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);
    };
});

次に、このモジュールは、MagentoによるKnockoutJSの使用を初期化するようMagento_Ui/js/lib/ko/initialize見えるモジュールをロードします。ただし、初期化モジュールのソースを見ると。

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();
});

ビューオブジェクトなしでko.applyBindings();オブジェクトと呼ばれるMagento が表示されます。これは意味をなさないし、Knockoutについての私の限られた理解なのか、Magentoがここで何かカスタム/奇妙なことをしているのかどうかはわからない。

これはMagentoが実際にKnockoutバインディングを適用する場所ですか?それとも他のどこかで起こりますか?または、MagentoはKnockoutコードをインターセプトして他の場所で処理するために何かトリッキーなことをしていますか?

回答:


38

Magento_Ui/js/lib/ko/initializeMagentoのは、そのノックアウトインスタンスを初期化した場合、ライブラリは、確かに、です。Magento 、バインディングを適用するときにViewModelを割り当てません

ここで見つからないキーは、という名前のカスタムKnockoutJSバインディングscopeです。

MagentoのKnockoutインスタンスがscope:このようなバインディングに遭遇したとき

<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>

そのバインディング(名前付きcustomer)の値を取得し、それを使用して、から内部ノードのViewModelをロードおよび適用しますuiRegistry。単純なKnockoutJS preデバッグを使用して、特定のスコープにバインドされたデータをデバッグできます。

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

uiRegistry実装されたオブジェクトのような単純な辞書、あるMagento_Ui/js/lib/registry/registryRequireJSモジュール。

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

オブジェクトは、次のようなJavaScriptのビットを介してレジストリに入れられます

<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>

Magento_Ui/js/core/appモジュール内のプログラムcomponentsは、渡されたオブジェクトのキーを調べ、各サブオブジェクトについて

  1. 指定されたRequireJSモジュールによって返されたオブジェクトをcomponentキーから取得します(Magento_Customer/js/view/customer

  2. そのオブジェクトを使用して、新しい javascript オブジェクトをインスタンス化します(以下を参照)

  3. 同じオブジェクトに追加のデータキーを割り当てます

  4. uiRegistry元のオブジェクトのキーを使用して同じオブジェクトを追加します(customer上記)

x-magento-initスクリプトがどのように機能するかわからない場合は、ここでその記事を書きました

この回答には、app.jsプロセスの詳細な調査があります。

スコープバインディングの実装はここで定義されます

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

アランそれは素晴らしい答えです!情報ありがとうございました。箇条書き3について、新しくインスタンス化されたオブジェクトに追加のデータキーを追加する方法。それはプロパティか何かですか?
-Timik
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.