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 的分享
我要留言