Як 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, якщо ви завантажуєте бекенд-сторінку з інтерфейсом Grid, Magento ініціалізує js/core/app.jsмодуль RequireJS

/**
 * 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_Ui/js/lib/ko/initializeмодуль, який, здається, ініціалізує використання Magento KnockoutJS. Однак якщо ви подивитесь на джерело модуля ініціалізації.

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

Ви бачите, що Magento називається ko.applyBindings();об'єктом без об'єкта перегляду . Це не має ніякого сенсу, і я не впевнений, чи це моє обмежене розуміння нокауту, або Magento робити щось на замовлення / дивне тут.

Це де Magento насправді застосовує нокаути на нокаут? Або це відбувається десь ще? Або Magento робить щось складне, щоб перехопити код Knockout і обробити його в іншому місці?

Відповіді:


38

The Magento_Ui/js/lib/ko/initializeБібліотека, на самому ділі, де Magento инициализирует екземпляр Knockout. Magento не призначає ViewModel, коли він застосовує прив'язки.

Тут відсутній ключ - власна прив'язка KnockoutJS з ім'ям scope.

Коли екземпляр Knockout Magento стикається з таким 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. Ви можете налагоджувати дані, пов'язані для певної області застосування, за допомогою простої preналагодження KnockoutJS

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

Це uiRegistryпростий словник, як об'єкт, реалізований в Magento_Ui/js/lib/registry/registryмодулі RequireJS.

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 кулі, як вона додасть додаткові ключі даних до нещодавно створеного об'єкта. Це будуть властивості чи щось інше?
Тімік
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.