Cách sử dụng Knockout JS trong Magento 2


12

Vấn đề của tôi:

Tôi đang cố gắng viết một ứng dụng Knockout JS nhỏ trong Magento 2, tôi đang vật lộn để khởi tạo ứng dụng vì khi tôi sử dụng ko.applyBindings(AppViewModel, document.getElementById("koTest"));nó sẽ phá vỡ Knockout được Magento sử dụng và ném lỗi này:

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

Tôi nghi ngờ đó là vì:

Tôi nghi ngờ điều này là do Magento 2 đã sử dụng ko.applyBindings()bên trong app/code/Magento/Ui/view/base/web/js/lib/knockout/bootstrap.js. Và vì điều đó không chỉ định một nút tôi không thể sử dụng ko.applyBindingslại.

Nếu tôi không sử dụng ko.applyBindings(AppViewModel, document.getElementById("koTest"))mã của mình thì ứng dụng của tôi sẽ không khởi tạo.

Điều này khiến tôi nghĩ rằng tôi cần phải bằng cách nào đó sử dụng ko.applyBindings()trong knockout / bootstrap.js nhưng tôi không biết làm thế nào, có ai có thể giúp đỡ không? Tôi có ít kinh nghiệm với Knockout.

Mã của tôi

<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
Có một hướng dẫn ở đây: inchoo.net/magento-2/knockout-js-in-magento-2
Aaron Allen

Câu trả lời:


23

Phương pháp đơn giản mà bạn KHÔNG cần sử dụng các mẫu html

Cảm ơn Vinai Kopp, cuối cùng tôi đã có câu trả lời cho vấn đề này, nó đơn giản hơn nhiều so với cách giải quyết trước đây của tôi (tôi đã làm sạch các nút). Tất cả những gì bạn cần làm là xác định 'ko'là một phụ thuộc và thêm mã của bạn vào trong hàm trả về.

Dưới đây là một ví dụ đơn giản thể hiện một số văn bản được truyền qua JSON.

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

Ở đây chúng tôi nói với Magento phạm vi của các thành phần của chúng tôi (điều này phải khớp data-bind: "scope: 'example-scope'"và chuyển bất kỳ dữ liệu bổ sung nào. Đây có thể là URL cơ sở, một thông điệp đơn giản, gần như mọi thứ bạn muốn. Tôi đã truyền một chuỗi (tiếng vang PHP) làm ví dụ

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

Và ở đây chúng tôi viết Javascript của chúng tôi.

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

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

 Kết quả

nhập mô tả hình ảnh ở đây

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

Phương pháp bạn cần sử dụng các mẫu HTML

Nếu bạn muốn sử dụng hệ thống tạo khuôn mẫu HTML trong Magento2 / Knockout (mà tôi cho rằng bạn sẽ cần cho bất kỳ phần công việc quan trọng nào), có một vài thay đổi bạn sẽ cần thực hiện so với câu trả lời đơn giản của tôi (bên dưới).

Nếu bạn không yêu cầu chức năng mẫu thì hãy cuộn xuống câu trả lời đơn giản cũ của tôi.

Các tệp tôi đang sử dụng cho ví dụ này là:

  • 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

Tệp mẫu PHTML

Thay đổi duy nhất đối với mẫu PHTML của chúng tôi là lệnh gọi getTemplate()hàm:

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

Tệp JS (thành phần)

Có một vài thay đổi bạn sẽ cần thực hiện đối với tệp JS, tôi sẽ trình bày chi tiết những điều dưới đây.

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 - Hàm trả về của bạn bây giờ cần mở rộng mô-đun uiComponent:

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

2 - Bạn cần thêm một initializechức năng và gọi this._super(). this._super()sẽ gọi hàm của thành phần cha có cùng tên. Vì vậy, trong trường hợp này tôi nghĩ rằng nó sẽ gọi initializecủa uiComponent.

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

3 - Tùy chọn - Bạn cũng có thể đặt một số giá trị mặc định cho thành phần của mình ở đây, tôi nghĩ rằng đây là một cách thực hành tốt vì nó làm cho thành phần của bạn dễ làm việc. Khi bạn sử dụng lại, bạn có thể giữ mặc định hoặc nếu bạn muốn tùy chỉnh nó, bạn có thể gọi nó với các đối số mới mà không thay đổi thành phần.

Ví dụ: nếu bạn nhìn vào các giá trị mặc định trong JS, nó sẽ đặt exampleMessagethành 'Hello?'trang đang hiển thị văn bản dưới dạng Hello Magento Stack Exchange!. Điều này là do tôi đã ghi đè lên exampleMessagetệp PHTML khi tôi gọi thành phần này.

Mẫu HTML

Tôi vẫn đang tìm hiểu kỹ xem các mẫu HTML có khả năng gì, tôi cho rằng các tính năng được đề cập trong tài liệu Knockout JS có thể được sử dụng ở đây khiến chúng khá linh hoạt.

Bây giờ tôi mới thêm một số văn bản ipsum lorem, tôi có thể sẽ cung cấp một câu hỏi / câu trả lời khác một khi tôi đã tìm ra những gì các mẫu HTML có thể làm.

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!

Kết quả và ghi đè mặc định

Như đã đề cập trước khi bạn có thể thấy rằng tôi đã ghi đè exampleMessagetrong mẫu, bạn có thể thấy nó hoạt động như văn bản đã đọc Hello Magento Stack Exchange.

nhập mô tả hình ảnh ở đây

Nếu tôi loại bỏ ghi đè trong tệp mẫu exampleMessagesẽ trở về mặc định của nó Hello?. Tôi đã cần phải xóa var/view_preprocessedpub/static/frontendsau khi thay đổi điều này mặc dù. Tôi đoán Magento đã lưu trữ giá trị.

nhập mô tả hình ảnh ở đây


Điều này sẽ hoạt động trong Magento2.1
Venkat

@Venkat - Bạn có nghĩa là bây giờ bạn có thể dễ dàng sử dụng Knockout mà không cần phải làm sạch nút? Hoặc bản sửa lỗi của tôi không hoạt động trong 2.1?
Ben Crook

Sửa chữa của bạn sẽ làm việc trong 2.1?
Venkat

Đối với tôi các ràng buộc đã hoạt động nhưng nhận được lỗi tham chiếu cho liên kết dữ liệu đầu vào đầu tiên
Venkat

Tôi nghĩ vậy vì KnockoutJS dường như không thay đổi nhiều kể từ 2.0.X - Tôi đã không thử nó trong 2.1 mặc dù vậy tôi không chắc chắn 100%. Ngoài ra, hãy đảm bảo bạn thực hiện một số thử nghiệm kỹ lưỡng vì tôi không chắc đây có phải là phương pháp tốt nhất hay không, đây là cách duy nhất tôi có thể tìm thấy.
Ben Crook

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.