วิธีใช้ Knockout JS ภายใน Magento 2


12

ปัญหาของฉัน:

ฉันกำลังพยายามเขียนแอป Knockout JS ขนาดเล็กภายใน Magento 2 ฉันพยายามที่จะเริ่มต้นแอปเนื่องจากเมื่อฉันใช้งานko.applyBindings(AppViewModel, document.getElementById("koTest"));มันจะทำให้ Knockout ที่ใช้โดย Magento ล้มเหลวและพ่นข้อผิดพลาดนี้:

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

ฉันสงสัยว่าเป็นเพราะ:

ฉันสงสัยว่านี้เป็นเพราะวีโอไอพี 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>

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 echo) เป็นตัวอย่าง

<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()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!

ผลลัพธ์และเขียนทับค่าเริ่มต้น

ดังกล่าวก่อนที่คุณจะเห็นว่าผมมีเขียนทับภายในแม่แบบที่คุณสามารถเห็นมันทำงานเป็นข้อความที่อ่านexampleMessageHello Magento Stack Exchange

ป้อนคำอธิบายรูปภาพที่นี่

ถ้าผมเอาแทนที่ในแฟ้มแม่แบบที่จะกลับไปมันเริ่มต้นของexampleMessage Hello?ฉันต้องการลบvar/view_preprocessedและpub/static/frontendหลังจากเปลี่ยนสิ่งนี้ ฉันเข้าใจว่าวีโอไอพีเก็บค่าไว้

ป้อนคำอธิบายรูปภาพที่นี่


สิ่งนี้จะทำงานใน Magento2.1
Venkat

@Venkat - คุณหมายความว่าตอนนี้คุณสามารถใช้สิ่งที่น่าพิศวงได้อย่างง่ายดายโดยไม่ต้องล้างโหนดหรือไม่ หรือว่าการแก้ไขของฉันทำงานใน 2.1?
Ben Crook

การแก้ไขของคุณจะทำงานใน 2.1?
Venkat

สำหรับฉันการผูกจะใช้งานได้ แต่ได้รับข้อผิดพลาดในการอ้างอิงสำหรับการผูกข้อมูลอินพุตครั้งแรก
Venkat

ฉันคิดอย่างนั้นเพราะ KnockoutJS ดูเหมือนจะไม่เปลี่ยนแปลงมากนักตั้งแต่ 2.0.X - ฉันไม่ได้ลองใน 2.1 แต่ฉันก็ไม่แน่ใจ 100% นอกจากนี้ตรวจสอบให้แน่ใจว่าคุณทำการทดสอบอย่างละเอียดเพราะฉันไม่แน่ใจว่านี่เป็นวิธีที่ดีที่สุดหรือเปล่า
Ben Crook

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.