Magento 2 | 在 AJAX 未完成時調用 Loader Widget
在 Magento 2 執行 AJAX 時,根據要獲取的數據、處理時間、服務器類型等等,請求可能需要的時間並不一定,開發人員藉由啟動 Loader 讓使用者知道正在進行加載程序並阻止使用者在 AJAX 完成之前執行任何操作直到回應接收完成,以防發生不可預期的錯誤。
本篇文章,我們將展示如何在 Magento 2 執行 AJAX 時調用 Loader Widget。
從這篇文章你會知道:
- 在 AJAX 未完成時調用 Loader Widget ,減少操作錯誤率,增進使用者體驗
Loading Mask 的執行邏輯
Loader 的功能描述於 vendor/magento/magento2-base/lib/web/mage/loader.js,其中有兩個關於功能的 widget 為 mage.loader(註冊事件以隱藏或顯示 Loading Mask)和 mage.loaderAjax(mage.loader 的觸發事件)。
下方範例中,我們創建一個按鈕,在單擊該按鈕後發送 AJAX 請求。 如果 “showLoader” 設置為 true,則在處理 AJAX 時將顯示 Loader。
<?php /** @var Magenest\LoadingScreen\Block\Ajax $block */ ?> <div id="send-ajax-form"> <button class="send-ajax-button"> <?= __("Send Ajax") ?> </button> <div class="msg"> </div> </div> <script> require(["jquery"], function ($) { $(".send-ajax-button").click(function (event) { event.preventDefault(); let url = "<?= $block->getUrl("ajax/ajax/test") ?>"; $.ajax({ url: url, type: 'GET', dataType: 'json', showLoader: true }).done(function (data){ $(".msg").text(data.msg); }) }) }) </script>
當調用 ajax 時,文檔會觸發事件,加載程序將捕獲此事件並調用 _onAjaxSend。 如果 ajax 完成,則會觸發 “ajaxComplete”。 在 onAjaxSend 方法中,它檢查 showLoader 選項是否設置為 true。 假設為真會觸發 processStart 事件(或在觸發 ajaxComplete 事件時觸發 processStop 事件)。
$.widget('mage.loaderAjax', { …, _bind: function () { $(document).on({ 'ajaxSend': this._onAjaxSend.bind(this), 'ajaxComplete': this._onAjaxComplete.bind(this) }); }, …, _onAjaxSend: function (e, jqxhr, settings) { var ctx; $(this.options.defaultContainer) .addClass(this.options.loadingClass) .attr({ 'aria-busy': true }); if (settings && settings.showLoader) { ctx = this._getJqueryObj(settings.loaderContext); ctx.trigger('processStart'); // Check to make sure the loader is there on the page if not report it on the console. // NOTE that this check should be removed before going live. It is just an aid to help // in finding the uses of the loader that maybe broken. if (window.console && !ctx.parents('[data-role="loader"]').length) { console.warn('Expected to start loader but did not find one in the dom'); } } }, _onAjaxComplete: function (e, jqxhr, settings) { $(this.options.defaultContainer) .removeClass(this.options.loadingClass) .attr('aria-busy', false); if (settings && settings.showLoader) { this._getJqueryObj(settings.loaderContext).trigger('processStop'); } } });
接下來,mage.loader widget 將捕獲事件 processStart,然後調用以顯示 Laoder。 最後再捕獲事件 processStop 以隱藏 Laoder。
$.widget('mage.loader', { …, _bind: function () { this._on({ 'processStop': 'hide', 'processStart': 'show', 'show.loader': 'show', 'hide.loader': 'hide', 'contentUpdated.loader': '_contentUpdated' }); }, …, show: function (e, ctx) { this._render(); this.loaderStarted++; this.spinner.show(); if (ctx) { this.spinner .css({ width: ctx.outerWidth(), height: ctx.outerHeight(), position: 'absolute' }) .position({ my: 'top left', at: 'top left', of: ctx }); } return false; }, hide: function () { if (this.loaderStarted > 0) { this.loaderStarted--; if (this.loaderStarted === 0) { this.spinner.hide(); } } return false; }, …, });
另一種啟動 Loading Mask 的方式 (可用於發送 AJAX 時或任何需要 Laoder 的情況)
…, $("body").on('processStart'); …, $("body").trigger('processStop');
在執行 AJAX 時顯示 Loading Mask 是個好的使用者體驗,讓使用者知道他們的請求正在處理中。接下來我們還會持續介紹各種簡易又好用的方法給大家!
以上就是歐斯瑞本次 在 AJAX 未完成時調用 Loader Widget 的分享
我要留言