Як користуватися Knockout JS в Magento 2


12

Моя проблема:

Я намагаюся написати невеликий додаток Knockout JS в Magento 2, я намагаюся ініціалізувати додаток, оскільки коли я ko.applyBindings(AppViewModel, document.getElementById("koTest"));його використовую, він руйнує нокаут, який використовує Magento, і видаляє цю помилку:

Uncaught Error: You cannot apply bindings multiple times to the same element.

Я підозрюю, що це через:

Я підозрюю, що це тому, що Magento 2 вже використовується ko.applyBindings()всередині app/code/Magento/Ui/view/base/web/js/lib/knockout/bootstrap.js. І оскільки це не вказує вузол, я не можу використовувати ko.applyBindingsзнову.

Якщо я не використовую ko.applyBindings(AppViewModel, document.getElementById("koTest"))код, тоді додаток не ініціалізується.

Це змушує мене думати, що мені потрібно якось використовувати ko.applyBindings()в нокауті / bootstrap.js, але я не маю уявлення, як хтось може допомогти? У мене мало досвіду з нокаутом.

Мій код

<script type="text/javascript">
    require([
        'ko'
    ], function(ko) {
        // This is a simple *viewmodel* - JavaScript that defines the data and behavior of your UI
        function AppViewModel() {

            this.firstName = ko.observable("Bert");
            this.lastName = ko.observable("Bertington");
            this.fullName = ko.computed(function() {
                return this.firstName() + " " + this.lastName();
            }, this);

            this.capitalizeLastName = function() {
                var currentVal = this.lastName();
                this.lastName(currentVal.toUpperCase());
            };
        }

        ko.applyBindings(AppViewModel, document.getElementById("koTest"));
    });
</script>

<!-- This is a *view* - HTML markup that defines the appearance of your UI -->

<div id="koTest">
    <p>First name: <strong data-bind="text: firstName"></strong></p>
    <p>Last name: <strong data-bind="text: lastName"></strong></p>
    <p>Full name: <strong data-bind="text: fullName"></strong></p>

    <p>First name: <input data-bind="value: firstName" /></p>
    <p>Last name: <input data-bind="value: lastName" /></p>
    <p>Full name: <input data-bind="value: fullName" /></p>

    <button data-bind="click: capitalizeLastName">Capitalise</button>
</div>

Відповіді:


23

Простий метод, де НЕ потрібно використовувати HTML-шаблони

Завдяки Вінаю Коппу я нарешті отримав відповідь на це, це набагато простіше, ніж у моєму попередньому хакітному вирішенні (я прибирав вузли). Все, що вам потрібно зробити, це визначити 'ko'як залежність і додати свій код у функцію повернення.

Нижче наводиться простий приклад, який відображає текст, переданий через JSON.

app/code/VENODR/MODULE/view/frontend/templates/knockout-example.phtml

Тут ми розповідаємо Magento про сферу наших компонентів (це повинно відповідати data-bind: "scope: 'example-scope'"і передавати будь-які додаткові дані. Це може бути базова URL-адреса, просте повідомлення, майже все, що вам потрібно. Я передав рядок (PHP-відлуння) як приклад

<script type="text/x-magento-init">
{
    "*": {
        "Magento_Ui/js/core/app": {
            "components": {
                "example-scope": {
                    "component": "VENDOR_MODULE/js/knockout-example",
                    "exampleMessage": "<?= __('Hello Magento Stack Exchange!') ?>"
                }
            }
        }
    }
}
</script>

<div data-bind="scope: 'example-scope'">
    <h2 data-bind="text: message"></h2>
</div>

І тут ми пишемо наш Javascript.

app/code/VENDOR/MODULE/view/frontend/web/js/knockout-example.js

define(['ko'], function(ko) {
    return function(config) {
        this.message = ko.observable(config.exampleMessage);
    }
});

 Результат

введіть тут опис зображення

---------------------

Метод, де НЕ потрібно використовувати шаблони HTML

Якщо ви хочете використовувати систему шаблонів HTML в Magento2 / Knockout (я вважаю, що вам знадобиться для будь-яких значних робіт), вам потрібно внести кілька змін порівняно з моєю спрощеною відповіддю (нижче).

Якщо вам не потрібна функціональність шаблону, тоді прокрутіть униз до моєї старої спрощеної відповіді.

Для цього прикладу використовуються файли:

  • app/design/frontend/VENDOR/THEME/Magento_Cms/templates/knockout.phtml
  • app/design/frontend/VENDOR/THEME/Magento_Cms/web/js/knockout-example.js
  • app/design/frontend/VENDOR/THEME/Magento_Cms/web/template/test.html

Файл шаблону PHTML

Єдина зміна нашого шаблону PHTML - це виклик getTemplate()функції:

<script type="text/x-magento-init">
{
    "*": {
        "Magento_Ui/js/core/app": {
            "components": {
                "example-scope": {
                    "component": "Magento_Cms/js/knockout-example",
                    "exampleMessage": "<?= __('Hello Magento Stack Exchange!') ?>"
                }
            }
        }
    }
}
</script>

<div data-bind="scope: 'example-scope'">
    <h2 data-bind="text: message"></h2>
    <!-- ko template: getTemplate() --><!-- /ko -->
</div>

Файл JS (компонент)

У файл JS потрібно внести декілька змін, я детально опишу їх нижче.

define(['ko', 'uiComponent'], function(ko, Component) {
    'use strict';

    return Component.extend({
        defaults: {
            exampleMessage: 'Hello?',
            template: 'Magento_Cms/test'
        },

        initialize: function() {
            this._super();
            console.log(this.exampleMessage);
            this.message = ko.observable(this.exampleMessage);
        }
    });
});

1 - Тепер ваша функція повернення повинна розширити модуль uiComponent:

return Component.extend({
    ...
});

2 - Вам потрібно додати initializeфункцію та зателефонувати this._super(). this._super()викличе функцію батьківського компонента з тим самим іменем. Так що в даному випадку я думаю , що він буде викликати initializeз uiComponent.

initialize: function() {
    this._super();
    ...
}.

3 - Необов’язково - Ви також можете встановити деякі типові параметри для свого компонента тут, я думаю, що це є хорошою практикою, яку слід дотримуватися, оскільки це полегшує роботу з вашим компонентом. При повторному використанні ви можете або зберегти за замовчуванням, або, якщо ви хочете налаштувати його, ви можете викликати його новими аргументами, не змінюючи компонент.

Наприклад, якщо ви дивитеся на значення по замовчуванням в JS вона встановлює exampleMessageна 'Hello?'ще сторінка робить текст як Hello Magento Stack Exchange!. Це тому, що я перезаписався exampleMessageу файл PHTML, коли я викликав компонент.

Шаблон HTML

Я все ще копаюся і бачу, на що здатні шаблони HTML, я припускаю, що функції, згадані в документації на Knockout JS, можна використовувати тут, роблячи їх досить гнучкими.

Я щойно додав текст lorem ipsum, я, швидше за все, надам ще одне питання / відповідь, як тільки я зрозумію, що можуть робити шаблони HTML.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Asperiores assumenda beatae blanditiis culpa cupiditate doloremque, expedita ipsum iure magni minima modi molestiae nulla optio porro ratione reiciendis repellat soluta voluptatum!

Результат і перезапис за замовчуванням

Як згадувалося раніше, ви можете побачити, що я переписав exampleMessageвсередині шаблону, ви можете бачити його, як текст читається Hello Magento Stack Exchange.

введіть тут опис зображення

Якщо я видалю перезапис у файлі шаблону, exampleMessageвін повернеться до значень за замовчуванням Hello?. Мені потрібно було видалити var/view_preprocessedі pub/static/frontendпісля зміни цього, хоча. Я припускаю, що Magento кеширував цінність.

введіть тут опис зображення


Це працюватиме в Magento2.1
Venkat

@Venkat - Ти маєш на увазі, що тепер ти можеш легко використовувати Knockout без очищення вузла? Або що моє виправлення працює в 2.1?
Бен Крук

Ваше виправлення буде працювати в 2.1?
Венкат

Для мене працює прив'язка, але отримання посилальної помилки для першого введення даних
Венкат

Я думаю, що так, як KnockoutJS, здається, не сильно змінився з 2.0.X - я не пробував цього в 2.1, хоча я не на 100% впевнений. Також переконайтеся, що ви провели ретельне тестування, оскільки я не впевнений, чи це найкращий метод, але це єдиний, який я можу знайти.
Бен Крук

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.