Nhập khẩu / Xuất khẩu `mặc định 'để làm gì trong Đối tượng bổ sung?


8

Trong nhiều hàm tạo mô hình khung nhìn UI Element của Magento 2, defaultsmảng sẽ có một importshoặc thuộc exportstính.

return Collection.extend({
    defaults: {
        //...
        imports: {
            rows: '${ $.provider }:data.items'
        },

return Insert.extend({
    defaults: {
        //...
        exports: {
            externalFiltersModifier: '${ $.externalProvider }:params.filters_modifier'
        },

Nhìn vào nguồn của uiElementmô-đun,

#File: vendor/magento/module-ui/view/base/web/js/lib/core/element/element.js
    initLinks: function () {
        return this.setListeners(this.listens)
                   .setLinks(this.links, 'imports')
                   .setLinks(this.links, 'exports')
                   .setLinks(this.exports, 'exports')
                   .setLinks(this.imports, 'imports');
    },

Những lần nhập / xuất này dường như có liên quan đến thông tin "liên kết" giữa các đối tượng khi một đối tượng được khởi tạo. Tuy nhiên, không rõ cách thức liên kết này hoạt động (dựa trên uiRegistry?) Hoặc cú pháp cho các chuỗi như thế ${ $.provider }:data.itemsnào. Rõ ràng các chuỗi này sử dụng các mẫu chữ mở rộng thành một cái gì đó như

foo_bar:data.items

Nhưng ý nghĩa của chuỗi cuối cùng này vẫn còn bí ẩn.

Có ai biết làm thế nào các thuộc tính nhập / xuất của các đối tượng này hoạt động?


Sẽ không đăng câu trả lời vì tôi chưa thực sự sử dụng chúng, nhưng các devdocs cung cấp thêm một chút thông tin chi tiết: devdocs.magento.com/guides/v2.1/ui-components/ Lỗi
Vinai

Câu trả lời:


21

Các thuộc tính này cho phép các thành phần được kết nối để chúng có thể tương tác với nhau. Nguyên tắc này hơi đơn giản: nhập (lấy) một giá trị từ một thành phần khác hoặc xuất (gửi) một giá trị sang một thành phần khác hoặc thực hiện cả hai.


Lưu ý: để duy trì sự rõ ràng trong câu trả lời này, "thành phần" là một đối tượng Javascript được RequireJS trả về, có một tên cụ thể và có thể được truy cập bằng tên đó thông qua UIRegistry.

Ngoài ra, tất cả các ví dụ dưới đây sẽ nằm trong thuộc defaults: {}tính của thành phần.


Với nguyên tắc được đặt ra, hãy bắt đầu với những gì tôi cho là khái niệm dễ nhất:

Nhập khẩu

Thuộc tính này lấy một giá trị từ một thành phần khác và gán nó cho thuộc tính được chỉ định. Trong ví dụ sau, chúng tôi khai báo nhập:

imports: {
    message: '${ $.provider }:data.message'
}

Khi Magento khởi tạo thành phần này, nó sẽ cố gắng gán giá trị cho thuộc messagetính. Khách sạn này sẽ có sẵn trong bối cảnh KnockoutJS. Tuy nhiên, như chúng ta biết , nó sẽ đánh giá giá imports.messagetrị dưới dạng biểu thức bằng chữ đầu tiên. Trong trường hợp này, Magento sẽ phân tích cú pháp $.providervà sẽ nhận được một giá trị. Mặc dù đó có thể là bất kỳ số lượng nào, trong ví dụ này và theo nhiều trường hợp sử dụng cốt lõi của Magento, đó là tên của một thành phần có trong sổ đăng ký UI. Điều đó sẽ được phân tích cú pháp trước bước tiếp theo.

messagetài sản là trong importstài sản, nó sẽ được chuyển đến setLinks()phương thức trong uiElement.initLinks(). Các setLinks()phương pháp là ở Magento/Ui/view/base/web/js/lib/core/element/links.js. Ở đó, nó lặp trên tất cả các thuộc tính (chỉ messageở đây) trong đối tượng được truyền vào ( importstrong trường hợp này). Trên các thuộc tính đó, nó sẽ cố gắng truyền dữ liệu từ thành phần này sang thành phần khác.

Các transfer()chức năng là nơi quan tâm tiếp theo. Ở đây, sổ đăng ký được tìm kiếm thành phần là "chủ sở hữu", trong trường hợp nhập. Thành phần này là thành phần hiện đang "sở hữu" hoặc có dữ liệu và sẽ là $.providerví dụ trong ví dụ trên. Nếu thành phần được tìm thấy, sau đó nó sẽ tiến hành liên kết dữ liệu với setLink()chức năng.

Có hai điều cần lưu ý trong phương thức đó: thứ nhất, nó đặt một trình lắng nghe sự kiện trên thuộc tính và thứ hai, nó sẽ ngay lập tức chuyển dữ liệu nếu cờ áp dụng đã được gửi. Trong thử nghiệm của tôi, nó luôn truyền immediatetham số để chuyển xảy ra trong quá trình khởi tạo. Tuy nhiên, do trình lắng nghe sự kiện được đính kèm trong bước đầu tiên, nó sẽ tiếp tục cập nhật các giá trị, nếu chúng thay đổi, để cả hai thành phần giữ nguyên trạng thái đồng bộ.

Sau đó, dữ liệu được đặt trên (hoặc, theo thuật ngữ đơn giản hơn: "được trả về thành phần") có thuộc imports: {}tính. Như tôi đã đề cập trước đó, sau đó nó được gán trực tiếp vào thuộc tính của thành phần đã khai báo nó - về cơ bản this.messagetrong ví dụ trên và không this.defaults.imports.message. Do đó, data-bind="text: messagesẽ hiển thị giá trị được trả về từ thuộc data.messagetính của thành phần được liên kết .

Cách tiếp cận này cho phép bạn xác định tên thuộc tính là gì trong thành phần nguồn. Trong ví dụ trên, bạn có thể sử dụng alertMessage: ...thay vì messagelàm tên thuộc tính của thành phần.

Xuất khẩu

Xuất khẩu là nghịch đảo của imports. Chúng dựa trên chức năng tương tự như nhập khẩu, nhưng thay vì lấy dữ liệu từ một thành phần và gán nó cho chính nó, nó sẽ gửi dữ liệu của chính nó đến một thành phần khác. Kết quả là gần như mọi thứ đều ngược lại. Lấy ví dụ này:

exports: {
    phoneNumber: '${ $.contactForm }:phone'
}

Trong ví dụ này, setLinks()lấy giá trị của thuộc tính của thành phần phoneNumbernày và gán nó cho thuộc phonetính của biểu mẫu liên hệ . Nó giống như tuyên bố rõ ràng một phonethuộc tính trong $.contactFormthành phần. Nếu không có bất kỳ thiết lập cụ thể nào trong $.contactForm, bạn có thể truy cập trực tiếp dữ liệu này. Có lẽ như thế này trong một mẫu Knockout : data-bind="text: phone.

Liên kết

Cuối cùng, linkstài sản giống như khai báo cả importsexportscho cùng một tài sản. Thoạt nhìn, điều này có vẻ giống như một tài liệu tham khảo tròn. Trong khi đó là theo một cách nào đó, có những lúc điều này có thể hữu ích. Mặc dù tôi chắc chắn có nhiều trường hợp sử dụng hơn, nhưng trường hợp tôi có thể thấy là khả năng một thành phần có thể thao tác dữ liệu từ một thành phần khác một cách linh hoạt. Trong trường hợp này, ElementA là nguồn của một số dữ liệu và hiển thị dữ liệu đó trên trang. Thành phần cần phải thao tác dữ liệu đó và vì vậy nó thuộc linkstính đó. Nó có thể vừa hiển thị dữ liệu vừa thao tác dữ liệu thực tế trong Thành phần mà không bao giờ mở rộng hoặc thay đổi Thành phần.

Tuy nhiên, một điều cần lưu ý là, theo mặc định, linkskhông phải là một cách để kết nối hai mô-đun khác. Nói cách khác, Thành phần không thể linkthành phầnA thành Thành phầnB. Nó là một phương pháp đồng bộ hai chiều với một thành phần khác.


Liên kết ( imports, exportslinks) hầu như luôn có thể tạo điều kiện cho các chức năng được gán cho các thuộc tính đó. Tôi gặp phải một số hành vi kỳ lạ trong khi tạo ra các vật thể quan sát và sử dụng linksnhưng nhìn chung nó hoạt động khá tốt.

Liên kết cung cấp các giá trị có sẵn trong phạm vi KnockoutJS và có thể được thao tác như bất kỳ thuộc tính nào khác. Và, để nhắc lại rõ ràng: hãy nhớ rằng imports, exportslinksđối tượng của các phím luôn luôn đề cập đến tính chất của các thành phần hiện tại (mà trong đó các thuộc tính đã được tuyên bố), trong khi gắn liền giá trị cho tên và thuộc tính của các thành phần từ xa .


Tóm lại, Magento sử dụng chức năng liên kết này để kết nối các thành phần khác nhau với nhau và đó là cách chúng ta có thể truy cập, cung cấp hoặc đồng bộ hóa dữ liệu với các thành phần khác.


Giải thích tuyệt vời @ bassplayer7 - Bạn có ví dụ nào về điều này không? Tôi hiểu cách thức hoạt động của nó nhưng đối với cuộc sống của tôi, tôi không thể có hai thành phần UI đơn giản của mình để chia sẻ một KO có thể quan sát được.
Ben Crook

@BenCrook, thật không may, tôi đã không làm được gì nhiều với điều này trong một thời gian vì vậy tôi không có quyền. Bây giờ tôi chắc chắn rằng bạn đã tìm ra nó, nhưng tôi khuyên bạn nên làm việc với importsexportshơn là links. Tôi đã tìm thấy linkslà tối nghĩa và dễ vỡ hơn. Nếu bạn đã đi qua một ví dụ, bạn có thể chia sẻ một liên kết?
bassplayer7

Tôi đã thử và thất bại trong việc nhập / xuất / liên kết hoạt động, Vinai đã trả lời câu hỏi ở đây mặc dù tôi chưa có cơ hội dùng thử.
Ben Crook

Thông tin này sẽ là tuyệt vời trên các tài liệu dev chính thức. Quá trình UI Cmponent chỉ là một con thú đáng sợ.
Nathaniel Rogers
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.