Không hiển thị trên màn hình nào


Câu trả lời:


22

Để hiểu những gì checkoutProviderdisplayArealà gì , trước tiên bạn phải hiểu phạm vi bạn đang tìm kiếm : jsLayout.

jsLayoutlà một loạt các cấu hình JavaScript cho các thành phần UI JavaScript trên trang thanh toán. Nếu bạn nhìn vào module-checkout/view/frontend/templates/onepage.phtml, bạn sẽ nhận thấy các x-magento-init-data sau :

<script type="text/x-magento-init">
    {
        "#checkout": {
            "Magento_Ui/js/core/app": <?php /* @escapeNotVerified */ echo $block->getJsLayout();?>
        }
    }
</script>

Đây là nơi mà tất cả bắt đầu. Nó nói:

Đối với phần tử #checkout, khởi tạo phần tử Magento_Ui/js/core/appvới thông tin sau: ...

Và thông tin mà nó nhận được là thông tin được tạo trong bố cục XML : jsLayout. Bây giờ, điều này có nghĩa là mọi thứ trong XML của bạn bây giờ được chuyển qua Magento_Ui/js/core/app-component (để lại các plugin và bộ xử lý bố cục và các công cụ ngoài phương trình trong thời điểm này ...)

Bây giờ, tôi sẽ không đi sâu vào chi tiết về cách làm module-ui/view/base/web/js/core/app.jssôi mọi thứ, bởi vì điều đó sẽ làm cho bài đăng này rất, rất dài, nhưng tóm tắt là thế này:

  • Các thành Magento_Ui/js/core/appphần tạo ra một thành checkoutphần.
  • Đây sẽ là một thành phần của loại uiComponent(đây là một thành phần rất chung có thể được sử dụng để trì hoãn các thành phần UI tùy chỉnh của riêng bạn. Nó đi kèm với kết xuất và mẫu kết xuất mẫu cơ bản).
  • Nó sẽ cho chúng tôi mẫu Magento_Checkout/web/frontend/template/onepage.html.
  • Nó sẽ tạo ra trẻ em khác nhau (với tên errors, estimation, steps, vv ...)
  • Đứa stepscon cũng sẽ là a uiComponent.
  • Chu kỳ này tiếp tục ... cấu hình làm cho trẻ em với các thông số khác nhau.

Bây giờ để đi đến displayAreaprovidercâu hỏi của bạn : Như bạn đã thấy ở trên, mọi thứ ánh xạ tới các lớp JavaScrip. Lần đầu tiên chúng ta thấy việc sử dụng displayArealà khi chúng ta tạo thành stepsphần, thuộc loại uiComponent. Vì vậy, uiComponentsẽ là một ứng cử viên hợp lý để tìm kiếm việc sử dụng displayArea.

Bây giờ, a uiComponentlà một lớp JavaScript của loại Magento_Ui/js/lib/core/collection. (Bạn có thể tra cứu điều này module-ui/view/base/requirejs-config.js). Bản đồ này để module-ui/view/base/web/js/lib/core/collection.js. Ở đây chúng tôi thấy cách sử dụng sau đây:

/**
 * Synchronizes multiple elements arrays with a core '_elems' container.
 * Performs elemets grouping by theirs 'displayArea' property.
 * @private
 *
 * @returns {Collection} Chainable.
 */
_updateCollection: function () {
    var _elems = compact(this._elems),
        grouped;

    grouped = _elems.filter(function (elem) {
        return elem.displayArea && _.isString(elem.displayArea);
    });
    grouped = _.groupBy(grouped, 'displayArea');

    _.each(grouped, this.updateRegion, this);

    this.elems(_elems);

    return this;
},

Vì vậy, những gì nó có hiệu lực, nó 'ánh xạ' một uiComponent đến một nhóm các thành phần UI nhất định. Điều này rất quan trọng để biết, vì nó cho phép chúng ta di chuyển các thành phần UI đến các vị trí khác trong bố cục, chỉ bằng cách thao tác bố cục XML, giống như bạn sẽ làm điều này với các phtmlmẫu được hiển thị phía máy chủ. Chỉ cần ghi đè displayAreavà bạn có thể kết xuất bất kỳ Thành phần giao diện người dùng JavaScript nào ở bất kỳ nơi nào khác (với điều kiện là khu vực đích cũng được hiển thị ở đâu đó).

Bây giờ cho câu hỏi thứ hai của bạn : provider. Giống như chúng ta đã nhìn lên displayArea, chúng ta nên bắt đầu nhìn vào Thành phần UI trước Magento_Checkout/js/view/form/element/email. Và nếu chúng ta nhìn vào requirejs-config.js, cuối cùng chúng ta cũng tìm thấy module-checkout/view/frontend/web/js/view/form/element/email.js.

Nhưng ... không providerđược sử dụng trong lớp này. Vì vậy, hãy xem liệu chúng ta có thể tìm thấy bất cứ thứ gì trong lớp mà nó mở rộng không: Component(lại là uiComponentlớp của chúng ta ).

Nhưng ... không providertốt. Chà, uiComponentchỉ đơn giản là kéo dài Element(nằm ở module-ui/view/base/web/js/lib/core/element/element.js), vì vậy chúng ta hãy nhìn qua đó:

/**
 * Parses 'modules' object and creates
 * async wrappers for specified components.
 *
 * @returns {Element} Chainable.
 */
initModules: function () {
    _.each(this.modules, function (name, property) {
        if (name) {
            this[property] = this.requestModule(name);
        }
    }, this);

    if (!_.isFunction(this.source)) {
        this.source = registry.get(this.provider);
    }

    return this;
},

Chơi lô tô! Nó chỉ ra rằng nhà cung cấp được sử dụng như một nguồn để lấy dữ liệu từ đó. Nếu chúng ta nhìn vào hàm tạo của Elementmặc định, bạn sẽ thấy rằng theo mặc định, nó được đặt thành trống:

provider: '',

Vì vậy, trở lại cấu hình của chúng tôi. Nếu bây giờ chúng ta đọc cấu hình của mình, chúng ta sẽ hiểu rằng vật phẩm shippingAddresslà một thành phần của Magento_Checkout/js/view/shipping, nó lấy dữ liệu của nó từ checkoutProvider.

Vì vậy, điều đó để lại cho chúng tôi hai câu hỏi:

  1. Trường hợp được checkoutProviderxác định?
  2. Làm thế nào nó được sử dụng trong JavaScript vận chuyển?

Chà, nếu bạn cuộn xuống phía dưới checkout_index_index.xml, bạn sẽ nhận thấy rằng nó chẳng khác gì một vani uiComponent:

<item name="checkoutProvider" xsi:type="array">
    <item name="component" xsi:type="string">uiComponent</item>
</item>

Và nếu bạn nhìn vào module-checkout/view/frontend/web/js/view/shipping.js, bạn sẽ thấy rằng nó được sử dụng như thế này:

registry.async('checkoutProvider')(function (checkoutProvider) {
    var shippingAddressData = checkoutData.getShippingAddressFromData();

    if (shippingAddressData) {
        checkoutProvider.set(
            'shippingAddress',
            $.extend({}, checkoutProvider.get('shippingAddress'), shippingAddressData)
        );
    }
    checkoutProvider.on('shippingAddress', function (shippingAddressData) {
        checkoutData.setShippingAddressFromData(shippingAddressData);
    });
});

Thành thật mà nói: đây là nơi phân tích của tôi dừng lại, bởi vì nó cũng khó tìm kiếm và đầu tư những gì đang diễn ra, nhưng tôi hy vọng ai đó có thể nhận nó từ đây ...

Tôi biết nó có liên quan đến việc registry.async()trả về một phương thức được thực thi ngay lập tức với hàm gọi lại làm đối số, nhưng người khác cần giải thích điều này ...


* Khước từ trách nhiệm: Bằng mọi cách, xin vui lòng sửa lỗi cho tôi nếu tôi sai! Không thử bất kỳ điều nào ở trên, nhưng tôi đã làm việc gần một năm nay với Magento 2 và tôi tin rằng đây là cách nó hoạt động. Thật không may, không có nhiều tài liệu nếu bạn muốn lặn xuống đáy đại dương Magento.


2
Vậy displayArea là gì?
Marián Zeke edaj

1
Đây là phân tích tuyệt vời, bạn đã bao giờ phát triển một sự hiểu biết thêm?
LM_Fielding

11

6 tháng sau câu trả lời ban đầu của tôi, tôi nghĩ rằng tôi có thể cung cấp một câu trả lời tốt hơn về những gì displayArea.

Theo hiểu biết của tôi, tất cả đều đi kèm với Knockouts ' getTemplate()-method, getRegion()-method và trẻ em trong các Thành phần UI. Một ví dụ tốt về điều này có thể được nhìn thấy khi bạn kiểm tra vendor/magento/module-checkout/view/frontend/templates/registration.phtmlvendor/magento/module-checkout/view/frontend/web/template/registration.html.

Trong registration.phtml, bạn sẽ thấy Thành phần giao diện người dùng Magento mặc định có con:

<script type="text/x-magento-init">
    {
        "#registration": {
            "Magento_Ui/js/core/app": {
               "components": {
                    "registration": {
                        "component": "Magento_Checkout/js/view/registration",
                        "config": {
                            "registrationUrl": "<?php /* @escapeNotVerified */ echo $block->getCreateAccountUrl(); ?>",
                            "email": "<?php /* @escapeNotVerified */ echo $block->getEmailAddress(); ?>"
                        },
                        "children": {
                            "errors": {
                                "component": "Magento_Ui/js/view/messages",
                                "sortOrder": 0,
                                "displayArea": "messages",
                                "config": {
                                    "autoHideTimeOut": -1
                                 }
                            }
                        }
                    }
                }
            }
        }
    }
</script>

Lưu ý việc sử dụng displayAreatrong children-node. Về cơ bản, nó nói với Knockout rằng phần tử con này sẽ được hiển thị trong một khu vực được gọi là 'tin nhắn' .

Bây giờ hãy xem trên cùng của registration.html:

<!-- ko foreach: getRegion('messages') -->
    <!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->

Dòng mã Knockout này về cơ bản là gì, nó lặp lại trên tất cả các phần tử con có trong displayArea 'message' và hiển thị chúng.

Về cơ bản, việc đặt tên hơi khó hiểu nếu bạn hỏi tôi. Tại sao bạn lại sử dụng 'displayArea' ở một nơi và 'khu vực' ở một nơi khác. Nhưng có lẽ giả định của tôi là hoàn toàn không chính xác. Có lẽ một nhà phát triển cốt lõi Magento có thể tỏa sáng hơn một chút về điều này?


1
Đây là điều khiến tôi bối rối quá lâu, tôi cứ nhìn thấy getRegionvà đầu óc tôi cứ nổ tung. Cảm ơn bạn cho cả hai câu trả lời bằng cách này, rất hữu ích!
Ben Crook

1
Vâng, đây chỉ là 2 xu của tôi. Tôi hy vọng ai đó của các nhà phát triển cốt lõi có thể chia sẻ một chút ánh sáng về chủ đề này. Các phần bên trong sâu hơn của Magento 2, và đặc biệt là toàn bộ triển khai Knockout / XHR là những thứ chưa được chứng minh rõ ràng.
Giel Berkers

2
Đồng ý, trừ khi bạn đi sâu vào nhiều tệp cốt lõi, gần như không có cách nào khác ngoài trao đổi ngăn xếp này để biết chuyện quái gì đang xảy ra.
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.