جاوااسکریپت/جیکوئری: $ (window).resize چگونه بعد از اتمام تغییر اندازه اجرا شود؟
من از JQuery به این صورت استفاده میکنم:
$(window).resize(function() { ... });
با این حال، به نظر میرسد که اگر فرد به صورت دستی اندازه پنجره مرورگر خود را با کشیدن لبه پنجره برای بزرگتر یا کوچکتر کردن تغییر دهد، رویداد .resize فوق چندین بار اجرا میشود.
سوال: چگونه میتوانم یک تابع را پس از اتمام تغییر اندازه پنجره مرورگر فراخوانی کنم (به طوری که این رویداد تنها یک بار رخ دهد)؟
پاسخ شماره ۱
در اینجا یک تغییر در راهحل CMS وجود دارد که میتوان آن را در چندین مکان از کد شما فراخوانی کرد:
var waitForFinalEvent = (function () {
var timers = {};
return function (callback, ms, uniqueId) {
if (!uniqueId) {
uniqueId = "Don't call this twice without a uniqueId";
}
if (timers[uniqueId]) {
clearTimeout (timers[uniqueId]);
}
timers[uniqueId] = setTimeout(callback, ms);
};
})();
طرز استفاده :
$(window).resize(function () {
waitForFinalEvent(function(){
alert('Resize...');
//...
}, 500, "some unique string");
});
راه حل CMS خوب است اگر فقط یک بار آن را فراخوانی کنید، اما اگر چندین بار آن را فراخوانی کنید، مثلاً اگر بخشهای مختلف کد شما کالبکهای جداگانهای برای تغییر اندازه پنجره تنظیم کنند، به دلیل اشتراک متغیر timer شکست خواهد خورد.
با این تغییر، شما یک شناسهی یکتا برای هر بازخوانی ارائه میدهید، و آن شناسههای یکتا برای نگه داشتن تمام رویدادهای زمانبندی شده بهصورت جداگانه استفاده میشوند.
پاسخ شماره ۲
من ترجیح میدهم یک رویداد ایجاد کنم:
$(window).bind('resizeEnd', function() {
//do something, window hasn't changed size in 500ms
});
در اینجا نحوه ایجاد آن آورده شده است:
$(window).resize(function() {
if(this.resizeTO) clearTimeout(this.resizeTO);
this.resizeTO = setTimeout(function() {
$(this).trigger('resizeEnd');
}, 500);
});
شما میتوانید این را در جایی در یک فایل جاوااسکریپت جهانی داشته باشید.
پاسخ شماره ۳
من از تابع زیر برای تأخیر در انجام اقدامات مکرر استفاده میکنم، این برای مورد شما کار خواهد کرد:
var delay = (function(){
var timer = 0;
return function(callback, ms){
clearTimeout (timer);
timer = setTimeout(callback, ms);
};
})();
طرز استفاده :
$(window).resize(function() {
delay(function(){
alert('Resize...');
//...
}, 500);
});
تابع callback که به آن پاس داده میشود، تنها زمانی اجرا میشود که آخرین فراخوانی delay پس از مقدار زمان مشخص شده انجام شده باشد، در غیر این صورت تایمر بازنشانی خواهد شد. من این را برای مقاصد دیگر مانند تشخیص زمانی که کاربر تایپ کردن را متوقف کرده است، مفید مییابم و غیره...
پاسخ شماره ۴
اگر شما Underscore.js را نصب کردهاید، میتوانید:
$(window).resize(_.debounce(function(){
alert("Resized");
},500));
پاسخ شماره ۵
برخی از راهحلهای ذکر شده قبلی برای من کار نکرد، حتی با اینکه استفاده عمومیتری داشتند. به طور جایگزین، من این مورد را پیدا کردم که هنگام تغییر اندازه پنجره جواب داد:
$(window).bind('resize', function(e){
window.resizeEvt;
$(window).resize(function(){
clearTimeout(window.resizeEvt);
window.resizeEvt = setTimeout(function(){
//code to do after window is resized
}, 250);
});
});
پاسخ شماره ۶
بسیار از دیوید والش متشکرم، اینجا یک نسخه ساده از debounce در underscore است.
کد :
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
استفاده ساده:
var myEfficientFn = debounce(function() {
// All the taxing stuff you do
}, 250);
$(window).on('resize', myEfficientFn);
مرجع: http://davidwalsh.name/javascript-debounce-function
