21- آموزش جاوااسکریپت | انتخاب چندعنصری در DOM
در این آموزش با انتخابگرهای چندعنصری DOM در جاوااسکریپت آشنا میشویم. چگونه با استفاده از getElementsByClassName، getElementsByTagName و querySelectorAll چند عنصر را بهصورت همزمان انتخاب کنیم، تفاوت HTMLCollection و NodeList را بشناسیم، آنها را در صورت نیاز به آرایه تبدیل کنیم
HTML استفاده شده در این پست همان HTML پست 19 است یک ul با کلاس collection داریم که شامل چند li با کلاس collection-item است و داخل هر آیتم نیز یک لینک قرار گرفته است
در آموزش قبلی با دو انتخابگر تکعنصری یعنی getElementById و querySelector آشنا شدیم. حالا وقت آن است که به سراغ انتخابگرهای چندعنصری (Multiple Element Selectors) برویم؛ انتخابگرهایی که برای انتخاب بیش از یک عنصر از DOM استفاده میشوند.
این انتخابگرها معمولاً یکی از دو نوع خروجی زیر را برمیگردانند:
HTMLCollectionNodeList
هر دوی اینها شبیه آرایه هستند، چون:
- با ایندکس قابل دسترسیاند
- ویژگی
lengthدارند
اما دقیقاً آرایه نیستند و بعضی از متدهای آرایه را بهصورت مستقیم پشتیبانی نمیکنند. البته در صورت نیاز میتوان آنها را بهآسانی به آرایه تبدیل کرد.
۱. متد document.getElementsByClassName
این متد تمام عناصری را که دارای یک کلاس مشخص هستند انتخاب میکند و خروجی آن یک HTMLCollection است.
فرض کنید چند آیتم لیست با کلاس collection-item داریم:
const items = document.getElementsByClassName('collection-item');
console.log(items);
با اجرای این کد، مجموعهای از تمام عناصر دارای این کلاس را دریافت میکنیم.
دسترسی به یک عنصر خاص
میتوان با استفاده از ایندکس به هر عنصر خاص دسترسی داشت:
console.log(items[0]);
تغییر استایل و محتوا
چون HTMLCollection شبیه آرایه است، میتوان از ایندکس برای اعمال تغییرات روی عناصر استفاده کرد:
items[0].style.color = 'red';
items[3].textContent = 'Hello';
در مثال بالا:
- رنگ اولین آیتم قرمز میشود
- متن آیتم چهارم به
Helloتغییر میکند
۲. انتخاب عناصر در محدوده یک عنصر خاص
یکی از نکات مهم این است که متد getElementsByClassName فقط روی document اجرا نمیشود؛ بلکه میتوان آن را روی یک عنصر خاص هم اعمال کرد.
مثلاً:
const listItems = document
.querySelector('ul')
.getElementsByClassName('collection-item');
console.log(listItems);
در این حالت، فقط عناصری با کلاس collection-item انتخاب میشوند که داخل ul قرار دارند.
این موضوع زمانی کاربردی است که بخواهیم جستجو را محدود به بخش مشخصی از صفحه کنیم و عناصر مشابه در سایر قسمتها نادیده گرفته شوند.
۳. متد document.getElementsByTagName
این متد بسیار شبیه getElementsByClassName عمل میکند، با این تفاوت که بهجای کلاس، عناصر را بر اساس نام تگ انتخاب میکند.
مثال:
const lis = document.getElementsByTagName('li');
console.log(lis);
خروجی این متد نیز یک HTMLCollection است.
دسترسی و تغییر عناصر
در اینجا هم میتوان مانند قبل با ایندکس به عناصر دسترسی داشت:
console.log(lis[0]);
lis[0].style.color = 'red';
lis[3].textContent = 'Hello';
بنابراین از نظر نحوه استفاده، این متد تقریباً مشابه getElementsByClassName است؛ فقط معیار انتخاب از کلاس به نام تگ تغییر میکند.
۴. تفاوت HTMLCollection با آرایه
همانطور که گفتیم، HTMLCollection آرایه نیست. مثلاً متدی مثل reverse() روی آن کار نمیکند:
const lis = document.getElementsByTagName('li');
lis.reverse(); // Error
این کد خطا میدهد، چون reverse یک متد مخصوص آرایه است.
تبدیل HTMLCollection به آرایه
برای استفاده از متدهای آرایه، میتوانیم از Array.from() استفاده کنیم:
let lis = document.getElementsByTagName('li');
lis = Array.from(lis);
lis.reverse();
console.log(lis);
حالا lis یک آرایه واقعی است و میتوانیم از متدهایی مثل reverse() یا forEach() روی آن استفاده کنیم.
استفاده از forEach
بعد از تبدیل به آرایه:
lis.forEach(function(li) {
console.log(li.className);
});
تغییر همه عناصر با forEach
مثلاً اگر بخواهیم متن همه آیتمها را تغییر دهیم:
lis.forEach(function(li, index) {
li.textContent = `${index}: Hello`;
});
در این مثال:
- متن تمام آیتمها تغییر میکند
- شماره ایندکس هر آیتم نیز نمایش داده میشود
۵. متد document.querySelectorAll
این متد یکی از پرکاربردترین انتخابگرهای چندعنصری در جاوااسکریپت مدرن است. تفاوت اصلی آن با دو متد قبلی در این است که خروجی آن یک NodeList است، نه HTMLCollection.
const items = document.querySelectorAll('ul.collection li.collection-item');
console.log(items);
مزیت اصلی querySelectorAll این است که:
- از سلکتورهای CSS پشتیبانی میکند
- خروجی آن
NodeListاست - معمولاً میتوان مستقیماً از
forEachروی آن استفاده کرد
تغییر متن عناصر با forEach
items.forEach(function(item, index) {
item.textContent = `${index}: Hello`;
});
در اینجا بدون نیاز به تبدیل به آرایه، میتوانیم روی همه عناصر پیمایش انجام دهیم.
۶. انتخاب عناصر فرد و زوج
در آموزش قبل دیدیم که querySelector فقط اولین عنصر مطابق را برمیگرداند، حتی اگر از انتخابگرهایی مثل :nth-child(odd) استفاده کنیم. اما حالا با querySelectorAll میتوانیم همه عناصر فرد یا زوج را انتخاب کنیم.
انتخاب آیتمهای فرد
const odd = document.querySelectorAll('li:nth-child(odd)');
odd.forEach(function(li) {
li.style.background = '#ccc';
});
انتخاب آیتمهای زوج
const even = document.querySelectorAll('li:nth-child(even)');
for (let i = 0; i < even.length; i++) {
even[i].style.background = '#f4f4f4';
}
در اینجا دو روش مختلف را دیدیم:
- استفاده از
forEachبرایNodeList - استفاده از حلقه
for
نکته مهم این است که حلقه for حتی روی HTMLCollection هم کار میکند، چون:
lengthدارد- با ایندکس قابل دسترسی است
جمعبندی
در این آموزش با مهمترین انتخابگرهای چندعنصری DOM در جاوااسکریپت آشنا شدیم:
getElementsByClassNamegetElementsByTagNamequerySelectorAll
همچنین تفاوت بین HTMLCollection و NodeList را بررسی کردیم و دیدیم که:
HTMLCollectionشبیه آرایه است اما آرایه نیستNodeListدر بسیاری از موارد راحتتر قابل پیمایش است- با
Array.from()میتوانHTMLCollectionرا به آرایه تبدیل کرد - با
forEachوforمیتوان روی مجموعهای از عناصر عملیات مختلف انجام داد
در آموزش بعدی، به سراغ Traversing DOM میرویم؛ یعنی یاد میگیریم چگونه بین والدها، فرزندان و عناصر همسایه در DOM حرکت کنیم.