jQuery والتعامل مع DOM
AJAX مع jQuery - الجزء الثاني
طرق AJAX المختصرة في jQuery
توفر jQuery طرقاً مختصرة ملائمة لعمليات AJAX الشائعة. تبسط هذه الطرق شيفرتك وتجعلها أكثر قابلية للقراءة، مع الاستمرار في توفير وظائف قوية.
الدالة $.get()
الدالة $.get() هي اختصار لإجراء طلبات GET:
البنية الأساسية:
$.get(url, data, callback, dataType);
// مثال
$.get('/api/users', { page: 1 }, function(data) {
console.log('المستخدمون:', data);
}, 'json');
مثال عملي: تحميل المنتجات
<div id="products-container"></div>
<button id="load-products">تحميل المنتجات</button>
<script>
$('#load-products').click(function() {
// طلب GET بسيط
$.get('https://fakestoreapi.com/products', function(products) {
var html = '';
products.slice(0, 5).forEach(function(product) {
html += '<div class="product-card">' +
'<h4>' + product.title + '</h4>' +
'<p>السعر: $' + product.price + '</p>' +
'<p>' + product.description.substring(0, 100) + '...</p>' +
'</div>';
});
$('#products-container').html(html);
});
});
</script>
الدالة $.post()
الدالة $.post() هي اختصار لإجراء طلبات POST:
البنية الأساسية:
$.post(url, data, callback, dataType);
// مثال
$.post('/api/register', { username: 'john', email: 'john@example.com' }, function(response) {
console.log('تم التسجيل:', response);
}, 'json');
مثال: إرسال بيانات النموذج
<form id="contact-form">
<input type="text" name="name" placeholder="الاسم" required>
<input type="email" name="email" placeholder="البريد الإلكتروني" required>
<textarea name="message" placeholder="الرسالة" required></textarea>
<button type="submit">إرسال الرسالة</button>
</form>
<div id="form-message"></div>
<script>
$('#contact-form').submit(function(e) {
e.preventDefault();
var formData = {
name: $('[name="name"]').val(),
email: $('[name="email"]').val(),
message: $('[name="message"]').val()
};
$.post('/api/contact', formData)
.done(function(response) {
$('#form-message').html(
'<div class="success">تم إرسال الرسالة بنجاح!</div>'
);
$('#contact-form')[0].reset();
})
.fail(function() {
$('#form-message').html(
'<div class="error">فشل إرسال الرسالة. يرجى المحاولة مرة أخرى.</div>'
);
});
});
</script>
الدالة $.getJSON()
الدالة $.getJSON() مصممة خصيصاً لجلب بيانات JSON:
مثال: تحميل بيانات الطقس
<div id="weather">
<button id="get-weather">الحصول على الطقس</button>
<div id="weather-info"></div>
</div>
<script>
$('#get-weather').click(function() {
var city = 'London';
var apiKey = 'your-api-key';
var url = 'https://api.openweathermap.org/data/2.5/weather';
$.getJSON(url, {
q: city,
appid: apiKey,
units: 'metric'
}, function(data) {
var html = '<h3>' + data.name + '</h3>' +
'<p>درجة الحرارة: ' + data.main.temp + '°C</p>' +
'<p>الطقس: ' + data.weather[0].description + '</p>' +
'<p>الرطوبة: ' + data.main.humidity + '%</p>';
$('#weather-info').html(html);
});
});
</script>
الدالة $.load()
تقوم الدالة $.load() بتحميل HTML من الخادم وإدراجه مباشرة في العناصر المحددة:
مثال: تحميل محتوى جزئي
<div id="header"></div>
<div id="sidebar"></div>
<div id="content"></div>
<script>
// تحميل الملفات الكاملة
$('#header').load('/templates/header.html');
$('#sidebar').load('/templates/sidebar.html');
// تحميل جزء محدد باستخدام المحدد
$('#content').load('/page.html #main-content');
// تحميل مع دالة استدعاء
$('#content').load('/article.html', function(response, status, xhr) {
if (status === 'error') {
$(this).html('<p>عذراً، لا يمكن تحميل المحتوى.</p>');
} else {
console.log('تم تحميل المحتوى بنجاح');
}
});
// تحميل مع معاملات
$('#results').load('/search.php', { query: 'jquery', limit: 10 });
</script>
نصيحة: الدالة $.load() فريدة من نوعها لأنها تُستدعى على تحديد jQuery، وليس على $ مباشرة. تقوم تلقائياً بإدراج الاستجابة في العناصر المطابقة.
واجهة الوعود مع .done() و .fail() و .always()
جميع دوال AJAX في jQuery تُرجع كائن jqXHR الذي ينفذ واجهة الوعود:
مثال: استخدام دوال الوعود
// سلسلة وعود أساسية
$.get('/api/user/1')
.done(function(data) {
console.log('نجح:', data);
})
.fail(function(xhr, status, error) {
console.log('خطأ:', error);
})
.always(function() {
console.log('اكتمل الطلب');
});
// معالجات متعددة
var request = $.getJSON('/api/products');
request.done(function(products) {
console.log('تم تحميل', products.length, 'منتجات');
});
request.done(function(products) {
$('#product-count').text(products.length);
});
request.fail(function() {
$('#error-message').show();
});
request.always(function() {
$('#loader').hide();
});
ربط طلبات AJAX المتعددة
مثال: الطلبات المتسلسلة
// تحميل المستخدم، ثم تحميل منشوراته، ثم تحميل التعليقات
$.get('/api/user/1')
.done(function(user) {
console.log('المستخدم:', user.name);
$('#user-name').text(user.name);
return $.get('/api/user/' + user.id + '/posts');
})
.done(function(posts) {
console.log('المنشورات:', posts.length);
$('#post-count').text(posts.length);
return $.get('/api/posts/' + posts[0].id + '/comments');
})
.done(function(comments) {
console.log('التعليقات:', comments.length);
$('#comment-count').text(comments.length);
})
.fail(function(error) {
console.log('خطأ في السلسلة:', error);
});
طلبات AJAX المتوازية مع $.when()
استخدم $.when() لتنفيذ الشيفرة بعد اكتمال طلبات AJAX المتعددة:
مثال: تحميل موارد متعددة
// تنفيذ طلبات متعددة بشكل متوازٍ
var usersRequest = $.get('/api/users');
var productsRequest = $.get('/api/products');
var categoriesRequest = $.get('/api/categories');
$.when(usersRequest, productsRequest, categoriesRequest)
.done(function(usersData, productsData, categoriesData) {
// جميع الطلبات الثلاثة اكتملت بنجاح
var users = usersData[0]; // العنصر الأول هو البيانات
var products = productsData[0];
var categories = categoriesData[0];
console.log('المستخدمون:', users.length);
console.log('المنتجات:', products.length);
console.log('الفئات:', categories.length);
// تهيئة لوحة المعلومات بجميع البيانات
initDashboard(users, products, categories);
})
.fail(function() {
console.log('فشل طلب واحد أو أكثر');
$('#error-message').text('فشل تحميل بيانات لوحة المعلومات');
})
.always(function() {
$('#loader').hide();
});
function initDashboard(users, products, categories) {
$('#total-users').text(users.length);
$('#total-products').text(products.length);
$('#total-categories').text(categories.length);
}
معالجات أحداث AJAX العامة
توفر jQuery أحداث AJAX عامة تُطلق لجميع طلبات AJAX:
مثال: مؤشر تحميل عام
<div id="global-loader" style="display: none;">جاري التحميل...</div>
<script>
// إظهار المحمل عند بدء أي طلب AJAX
$(document).ajaxStart(function() {
$('#global-loader').fadeIn();
});
// إخفاء المحمل عند اكتمال جميع طلبات AJAX
$(document).ajaxStop(function() {
$('#global-loader').fadeOut();
});
// تتبع نشاط AJAX
var activeRequests = 0;
$(document).ajaxSend(function(event, xhr, settings) {
activeRequests++;
console.log('بدأ الطلب:', settings.url);
console.log('الطلبات النشطة:', activeRequests);
});
$(document).ajaxComplete(function(event, xhr, settings) {
activeRequests--;
console.log('اكتمل الطلب:', settings.url);
console.log('الطلبات النشطة:', activeRequests);
});
// معالج خطأ عام
$(document).ajaxError(function(event, xhr, settings, error) {
console.error('خطأ AJAX:', settings.url, error);
if (xhr.status === 401) {
window.location.href = '/login';
}
});
// معالج نجاح عام
$(document).ajaxSuccess(function(event, xhr, settings) {
console.log('نجاح AJAX:', settings.url);
});
</script>
التخزين المؤقت لـ AJAX
مثال: تطبيق التخزين المؤقت لاستدعاءات API
var cache = {};
function getCachedData(url, forceRefresh) {
// التحقق من التخزين المؤقت وعدم إجبار التحديث
if (cache[url] && !forceRefresh) {
console.log('إرجاع البيانات المخزنة مؤقتاً لـ:', url);
return $.Deferred().resolve(cache[url]).promise();
}
// جلب من الخادم
console.log('جلب من الخادم:', url);
return $.get(url).done(function(data) {
cache[url] = data;
});
}
// الاستخدام
$('#load-users').click(function() {
getCachedData('/api/users')
.done(function(users) {
displayUsers(users);
});
});
$('#refresh-users').click(function() {
getCachedData('/api/users', true) // إجبار التحديث
.done(function(users) {
displayUsers(users);
});
});
// التخزين المؤقت مع انتهاء الصلاحية
var cacheWithExpiry = {};
function getCachedDataWithExpiry(url, ttl) {
var now = Date.now();
var cached = cacheWithExpiry[url];
// التحقق من التخزين المؤقت وعدم انتهاء الصلاحية
if (cached && (now - cached.timestamp < ttl)) {
console.log('إرجاع البيانات المخزنة مؤقتاً');
return $.Deferred().resolve(cached.data).promise();
}
// جلب من الخادم
return $.get(url).done(function(data) {
cacheWithExpiry[url] = {
data: data,
timestamp: now
};
});
}
// التخزين المؤقت لمدة 5 دقائق (300000 ميلي ثانية)
getCachedDataWithExpiry('/api/products', 300000)
.done(function(products) {
displayProducts(products);
});
إلغاء الطلب
مثال: إلغاء الطلبات الجارية
var currentRequest = null;
$('#search-input').on('input', function() {
var query = $(this).val();
// إلغاء الطلب السابق إذا كان لا يزال قيد التشغيل
if (currentRequest) {
currentRequest.abort();
console.log('تم إلغاء الطلب السابق');
}
// عدم البحث إذا كان الاستعلام قصيراً جداً
if (query.length < 3) {
$('#search-results').empty();
return;
}
// بدء طلب جديد
currentRequest = $.get('/api/search', { q: query })
.done(function(results) {
displaySearchResults(results);
})
.fail(function(xhr) {
if (xhr.statusText === 'abort') {
console.log('تم إلغاء الطلب');
} else {
console.log('فشل البحث');
}
})
.always(function() {
currentRequest = null;
});
});
function displaySearchResults(results) {
var html = '';
results.forEach(function(result) {
html += '<div class="result-item">' + result.title + '</div>';
});
$('#search-results').html(html);
}
إعدادات AJAX الافتراضية
مثال: تكوين الإعدادات الافتراضية العامة
// تعيين الخيارات الافتراضية لجميع طلبات AJAX
$.ajaxSetup({
timeout: 10000,
cache: false,
headers: {
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
},
beforeSend: function(xhr) {
var token = localStorage.getItem('auth_token');
if (token) {
xhr.setRequestHeader('Authorization', 'Bearer ' + token);
}
},
error: function(xhr) {
if (xhr.status === 401) {
console.log('غير مصرح - إعادة التوجيه إلى تسجيل الدخول');
window.location.href = '/login';
}
}
});
// جميع استدعاءات AJAX اللاحقة ستستخدم هذه الإعدادات الافتراضية
$.get('/api/protected-resource')
.done(function(data) {
console.log('البيانات:', data);
});
تحذير: استخدم $.ajaxSetup() بحذر. تؤثر الإعدادات الافتراضية العامة على جميع طلبات AJAX في تطبيقك. غالباً ما يكون من الأفضل إنشاء دوال غلاف لحالات استخدام محددة.
العمل مع أنواع محتوى مختلفة
مثال: إرسال تنسيقات بيانات مختلفة
// إرسال JSON
$.ajax({
url: '/api/data',
method: 'POST',
contentType: 'application/json',
data: JSON.stringify({ name: 'John', age: 30 }),
success: function(response) {
console.log('تم إرسال JSON بنجاح');
}
});
// إرسال بيانات مشفرة بالنموذج (افتراضي)
$.ajax({
url: '/api/data',
method: 'POST',
data: { name: 'John', age: 30 },
success: function(response) {
console.log('تم إرسال بيانات النموذج بنجاح');
}
});
// إرسال FormData (لتحميل الملفات)
var formData = new FormData();
formData.append('name', 'John');
formData.append('file', $('#file-input')[0].files[0]);
$.ajax({
url: '/api/upload',
method: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(response) {
console.log('تم تحميل الملف بنجاح');
}
});
تمرين عملي:
أنشئ لوحة معلومات لتحميل البيانات متعددة الخطوات:
- أنشئ ثلاثة طلبات متوازية لتحميل المستخدمين والمنشورات والتعليقات باستخدام $.when()
- اعرض مؤشر تحميل عام أثناء تقدم الطلبات
- أظهر الإحصائيات: إجمالي المستخدمين والمنشورات والتعليقات
- نفّذ التخزين المؤقت مع انتهاء صلاحية لمدة دقيقتين
- أضف زر "تحديث" لفرض إعادة التحميل من الخادم
- اعرض المستخدم الأكثر نشاطاً (المستخدم الذي لديه أكثر المنشورات)
- أظهر المنشورات الحديثة مع عدد التعليقات
- عالج الأخطاء بشكل صحيح وأظهر رسائل مناسبة
نقاط نهاية API:
- المستخدمون: https://jsonplaceholder.typicode.com/users
- المنشورات: https://jsonplaceholder.typicode.com/posts
- التعليقات: https://jsonplaceholder.typicode.com/comments
الخلاصة
في هذا الدرس، تعلمت:
- طرق AJAX المختصرة في jQuery: $.get()، $.post()، $.getJSON()، $.load()
- استخدام واجهة الوعود مع .done() و.fail() و.always()
- ربط طلبات AJAX المتسلسلة
- إجراء طلبات متوازية مع $.when()
- معالجات أحداث AJAX العامة لتتبع جميع الطلبات
- تطبيق استراتيجيات التخزين المؤقت
- إلغاء الطلبات الجارية
- تعيين إعدادات AJAX الافتراضية العامة مع $.ajaxSetup()
- العمل مع أنواع محتوى مختلفة
بعد ذلك، سنستكشف العمل مع النماذج والتسلسل لجمع وإرسال بيانات النموذج بكفاءة عبر AJAX.