Magento 2内でKnockout JSを使用する方法


12

私の問題:

Magento 2内で小さなKnockout JSアプリを書き込もうとしています。アプリを使用するko.applyBindings(AppViewModel, document.getElementById("koTest"));と、Magentoで使用されるKnockoutが壊れてこのエラーがスローされるため、アプリの初期化に苦労しています。

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()でknockout / 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>

1
ここにチュートリアルがあります:inchoo.net/magento-2/knockout-js-in-magento-2
Aaron Allen

回答:


23

HTMLテンプレートを使用する必要がない簡単な方法

Vinai Koppのおかげで、ようやくこれに対する答えを得ることができました。これは、以前のハッキーな回避策(ノードをクリーンアップしていた)よりもはるかに簡単です。必要なことは'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テンプレートを使用する必要がある方法

Magento2 / Knockout内でHTMLテンプレートシステムを使用したい場合(これは重要な作業に必要だと思います)、単純化した回答(下記)と比較して、いくつかの変更を加える必要があります。

テンプレート機能が必要ない場合は、下にスクロールして、以前の簡略化された回答を探します。

この例で使用しているファイルは次のとおりです。

  • 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-return関数でuiComponentモジュールを拡張する必要があります。

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

2- initialize関数を追加して呼び出す必要がありますthis._super()this._super()親コンポーネントの関数を同じ名前で呼び出します。したがって、この例では私は考えてそれが呼び出すinitializeuiComponent

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で機能しますか?
Ben Crook 2016

あなたの修正は2.1で動作しますか?
Venkat

私にとってバインディングは機能しますが、最初の入力データバインディングの参照エラーが発生します
Venkat

KnockoutJSは2.0.Xからそれほど変わっていないように思うので、2.1では試していないので、100%確実ではありません。また、これが最善の方法であるかどうかはわかりませんが、私が見つけることができる唯一の方法ですので、十分なテストを行ってください。
Ben Crook

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.