كيفية التعامل مع DOM: الدليل العملي الشامل للمبتدئين
مقدمة: لماذا يُعد DOM أساسياً في تطوير الواجهات؟
إذا كنت تتعلم تطوير الويب، فلا بد أنك سمعت عن DOM كثيراً. وقد يبدو هذا المفهوم غامضاً في البداية، لكنه في الحقيقة المفتاح الذي يتيح للغة JavaScript التفاعل مع الصفحة وتحديث محتواها وسلوكها بشكل حي ومباشر.
بمجرد أن تفهم آلية عمل DOM، ستتمكن من بناء واجهات أكثر تفاعلاً، مثل تغيير النصوص والصور، إضافة عناصر جديدة، حذف عناصر قديمة، تعديل التنسيقات، والاستجابة لنقرات المستخدم وإدخالاته.
في هذا الدليل سنشرح المفاهيم الأساسية بطريقة عملية، ثم ننتقل إلى أهم أساليب اختيار العناصر، والتنقل داخل الشجرة، وتعديل العناصر، والتعامل مع الأحداث.

خريطة المقال
- تعريف
DOMوالمفاهيم الأساسية - كيفية اختيار عناصر الصفحة
- كيفية التنقل داخل شجرة
DOM - طرق تعديل العناصر وإدارتها
- إضافة التنسيقات عبر
CSS - التعامل مع الأحداث في
DOM

ما هو DOM؟
يشير المصطلح DOM إلى Document Object Model، ويمكن فهمه ببساطة على أنه تمثيل شجري لصفحة HTML ينشئه المتصفح تلقائياً. كل عنصر في الصفحة يصبح عقدة Node داخل هذه الشجرة، ولكل عقدة خصائص ووسائل يمكن الوصول إليها وتعديلها باستخدام JavaScript.
هذه البنية هي التي تسمح لك مثلاً بتغيير محتوى فقرة، أو تحديث صورة، أو إضافة زر جديد، أو الاستجابة لنقرة المستخدم.

فهم العلاقات داخل شجرة DOM
لفهم DOM جيداً، من المهم التعرف على العلاقات بين العقد:
- العقدة العليا هي
document، وهي نقطة البداية لأي تعامل مع الصفحة. - العنصر
htmlيكون ابناً مباشراً لـdocument. - العنصران
headوbodyابنان للعنصرhtml، وهما في الوقت نفسه شقيقان. - كل عنصر قد يحتوي على أبناء مثل النصوص أو العناصر الأخرى أو السمات.
- العناصر التي تشترك في الأب نفسه تُسمى عناصر شقيقة
Siblings.
قد تبدو هذه الفكرة معقدة أول مرة، لكن مع التطبيق ستصبح بديهية للغاية.
كيفية اختيار العناصر في DOM
قبل أن تتمكن من تعديل أي عنصر، يجب أولاً تحديده. وتوفّر JavaScript أكثر من طريقة لاختيار عناصر الصفحة، ولكل طريقة استخدام مناسب.
1) الاختيار بواسطة getElementById()
تُعد هذه الطريقة من أكثر الطرق شيوعاً، إذ تعتمد على قيمة id الفريدة للعنصر.
<p id="master">i love javascript</p>
<script>
const masterEl = document.getElementById('master')
console.log(masterEl)
// <p id="master">i love javascript</p>
</script>
لاحظ أن قيمة id حساسة لحالة الأحرف، لذلك master تختلف عن Master.
2) الاختيار بواسطة getElementsByClassName()
تُرجع هذه الطريقة مجموعة من كل العناصر التي تحمل اسم الفئة class المحدد.
<p class="master2">i love javascript</p>
<p class="master2">i love react</p>
<h1 class="master2">i want a job</h1>
<button id="btn">click me</button>
<script>
const btn = document.getElementById('btn')
btn.addEventListener('click', function master() {
var master = document.getElementsByClassName('master2');
master[2].innerHTML = 'i need a job';
})
</script>
قبل النقر على الزر:

بعد النقر على الزر:

3) الاختيار بواسطة getElementsByTagName()
تُستخدم هذه الطريقة لاختيار كل العناصر التي تحمل اسم وسم معين مثل p أو div.
<p>VsCode</p>
<p>Atom</p>
<p>Sublime text</p>
<button id="btn">click me</button>
<script>
const btn = document.getElementById('btn')
btn.addEventListener('click', function master() {
let master = document.getElementsByTagName('p');
let masterEl = master[1].innerHTML = 'Code editors';
console.log(masterEl)
})
// <p>Atom</p> becomes <p>Code editors</p>
</script>
4) الاختيار باستخدام محددات CSS
هذه الطريقة مرنة جداً لأنها تسمح باستخدام محددات CSS مباشرة.
الطريقة querySelector()
تُرجع أول عنصر يطابق المحدد المُرسل إليها.
<div id="master">i am a frontend developer</div>
<script>
const master = document.querySelector('#master')
</script>
الطريقة querySelectorAll()
تُرجع قائمة بكل العناصر المطابقة للمحدد.
<p class="master">React</p>
<p class="master">Vue</p>
<p class="master">Angular</p>
<script>
const master = document.querySelectorAll('.master')
console.log(master[1])
// <p class="master">Vue</p>
</script>
أفضل طريقة للاختيار: توصية عملية
إذا كنت تريد اختيار عنصر وحيد ومحدد، فإن getElementById() أو querySelector() مع محدد id يُعدان خيارين ممتازين. أما إذا كنت بحاجة إلى التعامل مع مجموعة عناصر، فغالباً ما يكون querySelectorAll() أكثر مرونة ووضوحاً.
كيفية التنقل داخل شجرة DOM
بعد اختيار العنصر، تأتي مرحلة التنقل بين العلاقات المحيطة به، مثل الوصول إلى الأب، أو الأبناء، أو العناصر الشقيقة.
كل عنصر في الصفحة يُعد عقدة، وحتى النصوص داخل العناصر تُعامل على أنها عقد نصية.
مفاهيم مهمة قبل البدء
- لكل عقدة أب واحد فقط، باستثناء العقدة العليا.
- يمكن أن يكون للعقدة أكثر من ابن.
- العناصر الشقيقة هي العناصر التي تشترك في الأب نفسه.
خصائص شائعة للتنقل
parentNodechildrenfirstElementChildlastElementChildnextElementSiblingpreviousElementSibling
<div id="parent">
<div id="firstchild">i am a first child</div>
<p id="secondchild">i am the second child</p>
<h4>i am alive</h4>
<h1>hello world</h1>
<p>i am the last child</p>
</div>
const parent = document.getElementById('parent').lastElementChild
console.log(parent)
// <p>i am the last child</p>
const parent2 = document.getElementById('parent').children[3]
console.log(parent2)
// <h1>hello world</h1>
const secondchild = document.getElementById('secondchild')
console.log(secondchild)
// <p id="secondchild">i am the second child</p>
console.log(secondchild.parentNode)
// <div id="parent">...</div>
console.log(secondchild.nextElementSibling)
// <h4>i am alive</h4>
console.log(secondchild.previousElementSibling)
// <div id="firstchild">i am a first child</div>
كيفية تعديل عناصر DOM
معرفة طرق الاختيار والتنقل مهمة، لكن القيمة الحقيقية تظهر عندما تبدأ في تعديل الصفحة فعلياً. في هذا القسم سنغطي أكثر العمليات استخداماً.
هيكل المثال المستخدم
<div id="parent">
<div id="firstchild">i am a first child</div>
<p id="secondchild">i am the second child</p>
<h4>i am alive</h4>
<h1>hello world</h1>
<p>i am the last child</p>
</div>
إنشاء عنصر جديد باستخدام createElement()
const createEl = document.createElement('div')
console.log(createEl)
// <div></div>
حتى الآن أنشأنا عنصراً فارغاً فقط، لكنه لم يُعرض داخل الصفحة بعد.
تعيين المحتوى باستخدام innerHTML
const innerhtml = createEl.innerHTML = 'i am a frontend developer'
console.log(createEl)
// <div>i am a frontend developer</div>
يمكنك أيضاً استخدام textContent عندما لا تحتاج إلى إدخال شيفرة HTML داخل العنصر، وهو غالباً أكثر أماناً عند إدراج نصوص فقط.
إضافة العنصر إلى الصفحة باستخدام appendChild()
const createEl = document.createElement('div')
const innerhtml = createEl.innerHTML = 'i am a frontend developer'
const parentEl = document.getElementById('parent')
parentEl.appendChild(createEl)
console.log(parentEl)

إدراج عنصر قبل عنصر آخر باستخدام insertBefore()
إذا كنت لا تريد إضافة العنصر في نهاية الأب، يمكنك تحديد موضعه بدقة قبل عنصر موجود بالفعل.
const parentEl = document.getElementById('parent')
const firstchildEl = document.getElementById('firstchild')
const createEl = document.createElement('div')
const innerhtml = createEl.innerHTML = 'i am a frontend developer'
parentEl.insertBefore(createEl, firstchildEl)
console.log(parentEl)

استبدال عنصر بآخر باستخدام replaceChild()
const firstchildEl = document.getElementById('firstchild')
const parentEl = document.getElementById('parent')
const createEl = document.createElement('div')
const innerhtml = createEl.innerHTML = 'i am a frontend developer'
parentEl.replaceChild(createEl, firstchildEl)
console.log(parentEl)

حذف عنصر باستخدام removeChild()
const firstchildEl = document.getElementById('firstchild')
const parentEl = document.getElementById('parent')
parentEl.removeChild(firstchildEl)
console.log(parentEl)

إضافة التنسيقات للعناصر عبر JavaScript
لا يقتصر التعامل مع DOM على النصوص والعناصر فقط، بل يشمل أيضاً التحكم في التنسيقات. والطريقة الأكثر شيوعاً هي عبر التعامل مع classList.
إضافة فئة CSS باستخدام classList.add()
في المثال التالي، لدينا زر عادي. عند النقر عليه، ستُضاف إليه فئة تنسيقية جديدة.
<style>
body {
background-color: hotpink;
display: flex;
align-items: center;
}
.button {
background-color: blueviolet;
width: 200px;
border: none;
font-size: 2rem;
padding: 0.5rem;
border-radius: 5px;
cursor: pointer;
}
</style>
<button id="master">Click me</button>
const buttonEl = document.getElementById('master')
buttonEl.addEventListener('click', addFunction)
function addFunction() {
buttonEl.classList.add('button')
}


إزالة فئة باستخدام classList.remove()
const buttonEl = document.getElementById('master')
buttonEl.addEventListener('click', addFunction)
function addFunction() {
buttonEl.classList.remove('button')
}
عند التنفيذ، سيعود الزر إلى مظهره الافتراضي بعد إزالة الفئة.
التبديل بين الحالتين باستخدام classList.toggle()
const buttonEl = document.getElementById('master')
buttonEl.addEventListener('click', addFunction)
function addFunction() {
buttonEl.classList.toggle('button')
}
تُعد هذه الطريقة مثالية عندما تريد تشغيل النمط وإيقافه بالتناوب، مثل أزرار الإعجاب أو إظهار القوائم المنسدلة وإخفائها.
التعامل مع الأحداث في DOM
الأحداث هي كل ما يحدث للعناصر داخل الصفحة، مثل النقر على زر، أو الكتابة داخل حقل، أو تمرير مؤشر الفأرة، أو تحميل الصفحة.
ما المقصود بمعالج الأحداث؟
عندما يقع حدث معين، يمكن تشغيل دالة JavaScript لتنفيذ سلوك ما. وتُعرف هذه الدالة باسم معالج الحدث Event Handler.
استخدام addEventListener()
تُعد الدالة addEventListener() الأسلوب الحديث والمفضل لربط الأحداث بالعناصر، لأنها تفصل منطق JavaScript عن بنية HTML، مما يجعل الشيفرة أكثر ترتيباً وسهولة في الصيانة.
تستقبل addEventListener() عادة ثلاثة معاملات:
- نوع الحدث مثل
click. - الدالة التي ستُنفذ عند وقوع الحدث.
- قيمة منطقية اختيارية لتحديد أسلوب التقاط الحدث أو مروره.
كما يمكنك ربط أكثر من معالج حدث بالعنصر نفسه، وحتى أكثر من معالج للحدث نفسه إذا احتجت إلى ذلك.
نصائح عملية لإتقان التلاعب بـ DOM
- ابدأ دائماً بفهم بنية الصفحة قبل كتابة الشيفرة.
- استخدم
idللعناصر الفريدة عندما تحتاج إلى اختيار مباشر وسريع. - فضّل
querySelector()وquerySelectorAll()عندما تحتاج إلى مرونة أكبر. - تأكد من أن العنصر موجود في الصفحة قبل محاولة تعديله.
- درّب نفسك على بناء مشاريع صغيرة مثل آلة حاسبة، قائمة مهام، أو معرض صور تفاعلي.
الخلاصة التقنية
فهم DOM ليس مجرد خطوة تعليمية عابرة، بل هو مهارة جوهرية لأي مطور واجهات أمامية. فعندما تتقن اختيار العناصر، والتنقل بينها، وتعديلها، وإدارة تنسيقاتها وأحداثها، تصبح قادراً على بناء واجهات ديناميكية حقيقية باستخدام JavaScript. من الناحية العملية، أفضل طريق للإتقان هو تطبيق هذه المفاهيم في مشاريع صغيرة متكررة، لأن التعامل مع DOM يعتمد كثيراً على الممارسة أكثر من الحفظ.