التنقل في شجرة DOM عبر جافاسكربت: المفاهيم الأساسية والتقنيات المتقدمة
تمثل شجرة DOM (Document Object Model) الهيكل الهرمي المنظم لمحتوى صفحات الويب، حيث تُترجم العناصر والعُقد (Nodes) ضمن الصفحة إلى بنية شجرية يمكن الوصول إليها ومعالجتها باستخدام لغة جافاسكربت. ومن خلال هذه البنية، يصبح بالإمكان التنقل بين العناصر، التعديل عليها، حذفها أو حتى إنشاء عناصر جديدة بشكل ديناميكي. تعتبر القدرة على التنقل في شجرة DOM والتحكم بها ركيزة أساسية لتطوير واجهات مستخدم ديناميكية وتفاعلية.
يتناول هذا المقال، بشكل مفصل وموسع، كل ما يتعلق بالتنقل داخل شجرة DOM باستخدام جافاسكربت، مع شرح مفصل للمفاهيم الأساسية، والعلاقات بين العُقد، وأهم الطرق والدوال المستخدمة، مدعماً بأمثلة عملية وتقنيات متقدمة تساعد المطورين على التحكم الكامل في محتوى وهيكل صفحات الويب.
أولاً: ما هو DOM؟
DOM هو اختصار لـ Document Object Model، وهو واجهة برمجية تمثل هيكل الصفحة بصيغة كائنية (Object-Based)، تتيح للمطور التفاعل مع مكونات الصفحة HTML أو XML من خلال لغة جافاسكربت. تُحَوّل كل عناصر الصفحة — مثل العناصر
، وغيرها — إلى عُقد (Nodes) ضمن شجرة DOM.الشجرة تتكون من عدة أنواع من العُقد، منها:
-
Document: تمثل كامل المستند. -
Element: تمثل العناصر (tags) داخل الصفحة. -
Text: تمثل النصوص داخل العناصر. -
Attribute: تمثل خصائص العناصر. -
Comment: تمثل التعليقات.
ثانياً: الهيكل الشجري لعناصر DOM
تُبنى شجرة DOM على شكل بنية هرمية، تبدأ من الجذر (document)، وتنقسم إلى عناصر فرعية تمثل هيكل الصفحة، كما هو موضح في النموذج التالي:
html<html>
<head>
<title>مثالtitle>
head>
<body>
<div>
<p>نص داخل فقرةp>
div>
body>
html>
الشجرة تكون على النحو التالي:
-
document-
html-
head-
title
-
-
body-
div-
p-
Text Node
-
-
-
-
-
ثالثاً: طرق الوصول إلى العناصر داخل DOM
هناك عدة طرق يمكن من خلالها الوصول إلى عناصر DOM:
1. الوصول عبر المعرف (ID)
javascriptvar element = document.getElementById("myElement");
2. الوصول عبر اسم الوسم (Tag Name)
javascriptvar paragraphs = document.getElementsByTagName("p");
3. الوصول عبر الفئة (Class Name)
javascriptvar items = document.getElementsByClassName("item");
4. الوصول عبر المحددات (Selectors)
javascriptvar div = document.querySelector("div.container");
var allItems = document.querySelectorAll("ul li");
رابعاً: العلاقات بين العُقد في DOM
لفهم كيفية التنقل داخل الشجرة، يجب معرفة العلاقات بين العُقد:
| العلاقة | التفسير |
|---|---|
parentNode |
العقدة الأم للعقدة الحالية |
childNodes |
قائمة بجميع الأبناء (بما فيهم النصوص) |
children |
قائمة الأبناء من نوع Element فقط |
firstChild / firstElementChild |
أول عنصر ابن |
lastChild / lastElementChild |
آخر عنصر ابن |
nextSibling / nextElementSibling |
الأخ التالي في نفس المستوى |
previousSibling / previousElementSibling |
الأخ السابق في نفس المستوى |
خامساً: التنقل العمودي (بين الأبناء والأمهات)
الانتقال إلى العنصر الأب:
javascriptvar parent = element.parentNode;
الوصول إلى الأطفال:
javascriptvar children = element.childNodes; // تشمل النصوص
var elementsOnly = element.children; // عناصر فقط
الحصول على أول وآخر طفل:
javascriptvar first = element.firstElementChild;
var last = element.lastElementChild;
سادساً: التنقل الأفقي (بين الإخوة)
javascriptvar next = element.nextElementSibling;
var prev = element.previousElementSibling;
هذه الدوال تُستخدم للتنقل بين العناصر التي تقع على نفس المستوى في الشجرة، وهي مفيدة على سبيل المثال عند التعامل مع قوائم أو مجموعات من العناصر المتشابهة.
سابعاً: التحقق من نوع العقدة
يمكن التحقق من نوع العقدة باستخدام nodeType، حيث:
| النوع | القيمة | الوصف |
|---|---|---|
| Element | 1 | عقدة عنصر |
| Attribute | 2 | خاصية |
| Text | 3 | نص |
| Comment | 8 | تعليق |
| Document | 9 | المستند |
مثال:
javascriptif (node.nodeType === 1) {
console.log("هذا عنصر HTML");
}
ثامناً: التكرار على العُقد
يمكن استخدام الحلقات للتكرار عبر عناصر DOM:
مثال باستخدام for:
javascriptvar children = element.children;
for (var i = 0; i < children.length; i++) {
console.log(children[i].tagName);
}
مثال باستخدام forEach (مع querySelectorAll):
javascriptdocument.querySelectorAll("p").forEach(function(p) {
p.style.color = "blue";
});
تاسعاً: تعديل DOM أثناء التنقل
من خلال التنقل، يمكن تعديل المحتوى أو البنية:
تعديل النص:
javascriptelement.textContent = "نص جديد";
تعديل HTML داخلي:
javascriptelement.innerHTML = "نص جديد";
إنشاء عناصر وإضافتها:
javascriptvar newElement = document.createElement("span");
newElement.textContent = "عنصر جديد";
parent.appendChild(newElement);
حذف العناصر:
javascriptparent.removeChild(child);
عاشراً: تطبيقات عملية للتنقل داخل DOM
1. إنشاء قائمة ديناميكية
javascriptvar list = document.createElement("ul");
var items = ["تفاحة", "موز", "برتقال"];
items.forEach(function(item) {
var li = document.createElement("li");
li.textContent = item;
list.appendChild(li);
});
document.body.appendChild(list);
2. تلوين كل فقرة حسب ترتيبها
javascriptvar paragraphs = document.querySelectorAll("p");
paragraphs.forEach(function(p, index) {
if (index % 2 === 0) {
p.style.backgroundColor = "lightgray";
} else {
p.style.backgroundColor = "white";
}
});
الحادي عشر: التعامل مع الأحداث أثناء التنقل
أثناء التنقل، يمكن إرفاق أحداث DOM ديناميكيًا:
javascriptvar buttons = document.querySelectorAll("button");
buttons.forEach(function(btn) {
btn.addEventListener("click", function() {
alert("تم الضغط على الزر: " + btn.textContent);
});
});
الثاني عشر: التقنيات المتقدمة في التعامل مع DOM
استخدام Tree Walker
TreeWalker يتيح التنقل عبر الشجرة حسب معايير معينة:
javascriptvar walker = document.createTreeWalker(
document.body,
NodeFilter.SHOW_ELEMENT,
null,
false
);
while(walker.nextNode()) {
console.log(walker.currentNode.tagName);
}
استخدام NodeIterator
javascriptvar iterator = document.createNodeIterator(
document.body,
NodeFilter.SHOW_TEXT,
null
);
var node;
while (node = iterator.nextNode()) {
console.log(node.textContent.trim());
}
جدول يوضح أهم خصائص التنقل في DOM
| الخاصية | الوصف | نوع العقد المعادة |
|---|---|---|
parentNode |
العقدة الأم | Node |
children |
قائمة العناصر الأبناء | HTMLCollection |
childNodes |
كل الأبناء (عناصر + نصوص + تعليقات) | NodeList |
firstElementChild |
أول عنصر ابن | Element |
lastElementChild |
آخر عنصر ابن | Element |
nextElementSibling |
العنصر التالي في نفس المستوى | Element |
previousElementSibling |
العنصر السابق في نفس المستوى | Element |
الثالث عشر: الأداء والاعتبارات الأمنية
الأداء
-
يفضل استخدام
childrenبدلًا منchildNodesإذا لم تكن بحاجة للنصوص، لتقليل عدد العقد المعالجة. -
التكرار باستخدام
forأكثر كفاءة منforEachفي الحلقات الكبيرة.
الأمان
-
تجنب استخدام
innerHTMLمع المحتوى المأخوذ من المستخدم، لتفادي XSS (تنفيذ أكواد خبيثة). -
الأفضل استخدام
textContentأوcreateElementوappendChild.
المراجع
-
Mozilla Developer Network (MDN): https://developer.mozilla.org
-
W3C DOM Standard: https://www.w3.org/DOM

