Lang thang trên mạng thì tìm được một bài viết về require js trong Magento 2, nên copy về chia sẻ cho các bạn.
Nguồn bài viết: https://nghiata1987.wordpress.com/2020/05/02/mot-so-ky-thuat-su-dung-requirejs-trong-magento-2/
Bài viết này tương đối ngắn đề cập đến chủ đề liên quan tới Javascript trong Magento 2. Bạn đọc chỉ cần hiểu biết cơ bản về Magento & Javascript là đủ.
Đây là một trong những kỹ thuật quan trọng giúp ta quản lý, hoặc tùy biến Javascript mà tránh khỏi xung đột code. Nó cũng có thể khiến chúng ta liên tưởng tới DI hay interceptors tuy nhiên vẫn có nhiều hạn chế.
Trước hết trong view/adminhtml hay view/frontend, tùy theo mục đích của bạn, tạo file requirejs-config.js. Bạn có thể đọc kỹ hơn tại đây.
Phần 1: Tóm tắt các kỹ thuật sử dụng trong requireJS
Tổng thể chung về Requirejs-config.js như sau:
1 2 3 4 5 6 7 8 9 10 |
var config = { 'map': {...}, 'paths': {...}, 'deps':[...], 'shim': {...}, 'config': { 'mixins': {...}, 'text': {...} } } |
Map dùng để cấu hình các module có thể được sử dụng trong define([], function() { }), bởi alias (bí danh) của nó. Ví dụ:
1 2 3 4 5 |
map: { '*': { alias: 'Vendor_Module/js/complex/path/amd-module' } } |
‘*’ chính là chỉ phạm vi sử dụng alias này, ý nó nói rằng bất kỳ module nào cũng có thể dùng được. Nếu chúng ta không sài alias, chúng ta có thể sài thẳng đường link bên trên khi khai báo trong define().
Paths, Cách sử dụng nó khá giống với map nhưng áp dụng được cả cho HTML template và link bên ngoài.
1 2 3 4 |
paths: { 'alias': 'library/file', 'another-alias': 'https://some-library.com/file' } |
Deps, một cách để quản lý JS dependencies, khi khai báo deps thì tất cả các page đều sẽ load thư viện đó. Ngoài ra còn có cách sử dụng Shim, sẽ được đề cập tiếp theo.
1 |
deps: ['Vendor_Module/js/module'] |
Shim được sử dụng khi cần thêm dependencies tới một thư viện thứ 3, thứ mà ta không modify được, ví dụ: khi bạn dùng một thư viện JS hiển thị 3D nào đó, nhưng nó cần có Jquery chẳng hạn, thì ta cần phải sử dụng Shim, nếu ko ta có thể dính lỗi không tìm thấy thư viện được yêu cầu, rất nguy hiểm (một trong những lỗi phổ biến ở Magento 2.0.x). Ngoài việc thêm dependencies, shim còn thay đổi thứ tự Load file, để đảm bảo thư viện được yêu cầu phải được load trước.
1 2 3 4 5 6 7 |
shim: { '3rd-party-library': ['myJSFile'], 'another-3rd-party-library': { deps: ['myJSFile'], exports: 'another3rdPartyLibrary' } } |
another-3rd-party-library phụ thuộc vào myJSFile, và có thể được sài giống như alias another3rdPartyLibrary.
Mixins, kỹ thuật cực kỳ hữu dụng, cho phép chúng ta ghi đè các phương thức của một AMD module thứ mà trả về UI component, jQuery Widget hay JS object.
1 2 3 4 5 6 7 |
'config': { 'mixins': { 'Vendor_Module/js/module': { 'Vendor_Module/js/module-mixin': true } } } |
Text, được sử dụng để thiết lập security request headers. Ví dụ:
1 2 3 4 5 6 7 |
'config': { 'text': { 'headers': { 'X-Requested-With': 'XMLHttpRequest' } } } |
Nếu không có Cross Origin Resource Sharing (CORS), thì việc thêm vào X-requested-with là bất khả thi. Lỗi này có thể dẫn tới việc trên console của chrome, bạn sẽ nhìn thấy lỗi bôi đỏ liên quan đến cross domain.
Phần 2: Mixins và cách sử dụng
File mixin thường được lưu trong thư mục web/js thuộc frontend, hoặc adminhtml. Về bản chất, nó chính là một AMD module.
Mặc định rằng tất cả các JS mixin file đều đã được khai báo trong requirejs-config.js
Ví dụ 1: Extend một UI component
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
define(function () { 'use strict'; var mixin = { /** * * @param {Column} elem */ isDisabled: function (elem) { return elem.blockVisibility || this._super(); } }; return function (target) { // target == Result that Magento_Ui/.../columns returns. return target.extend(mixin); // new result that all other modules receive }; }); |
Mình chưa từng dùng theo cách trên, nhưng mình đã từng mở rộng một function của Ui Component theo cách khác. Nên mình xin update thêm cách bên dưới để các bạn có thêm tùy chọn:
1 2 3 4 5 6 7 8 9 |
define([], function () { 'use strict'; return function (Component) { return Component.extend({ //function mà bạn muốn mở rộng được viết ở đây }); } }); |
Ví dụ 2: Extends một JQuery widget, ở ví dụ này là modal-widget. Trên thực tế text trong ví dụ sẽ phải dùng một thư viện JS trong Magento 2 để đảm bảo có thể translate sang ngôn ngữ khác. Tuy nhiên ta không sài nó ở đây.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
define(['jquery'], function ($) { 'use strict'; var modalWidgetMixin = { options: { confirmMessage: "Please, confirm modal closing." }, /** * Added confirming for modal closing * * @returns {Element} */ closeModal: function () { if (!confirm(this.options.confirmMessage)) { return this.element; } return this._super(); } }; return function (targetWidget) { // Example how to extend a widget by mixin object $.widget('mage.modal', targetWidget, modalWidgetMixin); // the widget alias should be like for the target widget return $.mage.modal; // the widget by parent alias should be returned }; }); |
Ví dụ 3: Extend một object, sử dụng khi file Javascript ta muốn can thiệp trả về một đối tượng, trường hợp này, ta cần sử dụng 1 util JS function đó là wrapper. Khi bạn xây dựng module One Step Checkout thì đây là một trong những kỹ thuật cần biết.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
define([ 'mage/utils/wrapper' ], function (wrapper) { 'use strict'; return function (stepNavigator) { stepNavigator.setHash = wrapper.wrapSuper(stepNavigator.setHash, function (hash) { this._super(hash); // add extended functionality here or modify method logic altogether }); return stepNavigator; }; }); |
Ví dụ 4: Extend một function, ta dùng rất nhiều kỹ thuật này trong Magento, đặc biệt hữu dụng trong việc biến đổi function mà không gây nên coding conflict. Dưới đây là 1 đoạn code để biến đổi function trong file nguyên bản dưới đây.
Magento/Checkout/view/frontend/web/js/proceed-to-checkout.js
1 2 3 4 5 6 7 8 9 10 11 12 |
define([ 'mage/utils/wrapper' ], function (wrapper) { 'use strict'; return function (proceedToCheckoutFunction) { return wrapper.wrap(proceedToCheckoutFunction, function (originalProceedToCheckoutFunction, config, element) { originalProceedToCheckoutFunction(config, element); // add extended functionality here }); }; }); |
Một vài ví dụ cụ thể được Magento sử dụng:
view/frontend/web/js/model/place-order-mixin.js
view/frontend/web/js/model/set-payment-information-mixin.js
Kết luận
Nếu các bạn biết những cách hay ho dùng để mở rộng hoặc override js trong Magento 2, thì đừng ngại để lại một bình luận chia sẻ cho mọi người nhé. Thanks.