Javaبرنامج تعليمي حول DOM النصي مع مثال
⚡ ملخص ذكي
Javaتمنح Script DOM و Events البرامج النصية تحكمًا كاملاً في صفحة الويب، مما يسمح للتعليمات البرمجية بقراءة أو تغيير أو إضافة أو إزالة أي عنصر قام المتصفح بعرضه، ثم الاستجابة على الفور كلما قام الزائر بالنقر أو الكتابة أو التمرير.

ما هو DOM في Javaالبرنامج النصي؟
Javaيمكن للبرامج النصية الوصول إلى جميع عناصر صفحة الويب باستخدام نموذج كائن المستند (DOM). في الواقع، يقوم متصفح الويب بإنشاء نموذج DOM لصفحة الويب عند تحميلها. يُنشأ نموذج DOM على شكل شجرة من الكائنات كما يلي:
يُصبح كل عنصر HTML في الصفحة عقدةً داخل هذه الشجرة. تُصنّف المتصفحات عقد DOM إلى أنواع أساسية قليلة: تمثل عقد العناصر علامات مثل <p> or <div>تحتوي عقد النص على الكلمات المرئية داخل الوسم، بينما تخزن عقد السمات قيمًا مثل id or classوتحافظ عقد التعليق على <!-- --> الترميز. العقدة العلوية هي دائمًا document الكائن، وكل عنصر آخر هو سليل له.
باستخدام DOM، Javaسيناريو يمكنه القيام بمهام متعددة. يمكنه إنشاء عناصر وخصائص جديدة، وتغيير العناصر والخصائص الموجودة، وحتى إزالة العناصر والخصائص الموجودة. Javaيمكن للبرمجة النصية أيضًا التفاعل مع الأحداث الموجودة وإنشاء أحداث جديدة على الصفحة. تشرح الأقسام التالية كيفية تحديد العناصر وتعديلها وربط معالجات الأحداث بأمثلة عملية قابلة للتنفيذ.
من المفيد أن نتذكر أن نموذج كائن المستند (DOM) ليس هو نفسه ملف HTML المصدر. فملف HTML الذي يقوم المتصفح بتنزيله هو نص ثابت، بينما نموذج كائن المستند (DOM) الذي يبنيه من هذا النص هو نموذج كائن حي وديناميكي. أي تغيير Javaيظهر النص البرمجي الذي يتم إنشاؤه في DOM على الشاشة على الفور، دون أن يتم لمس ملف HTML الأصلي على الإطلاق.
كيفية تحديد عناصر DOM في Javaسيناريو
قبل Javaيمكن للبرامج النصية تغيير أي شيء في الصفحة، ولكنها تحتاج أولاً إلى تحديد العنصر المستهدف. يوفر نموذج كائن المستند (DOM) عدة طرق لتحديد العنصر، كل منها مناسب لحالات مختلفة.
- getElementById(): تُعيد العنصر الوحيد الذي يُطابق عنصرًا مُحددًا
idالسمة. - getElementsByClassName(): يُعيد هذا الكود مجموعة HTML حية تحتوي على كل عنصر يحمل فئة معينة.
- getElementsByTagName(): تُعيد هذه الدالة مجموعة HTML حية تحتوي على جميع العناصر التي تحمل اسم وسم معين، مثل:
porli. - querySelector(): تُعيد هذه الدالة أول عنصر يطابق أي مُحدِّد CSS.
- querySelectorAll(): تُرجع قائمة عقد ثابتة تحتوي على كل عنصر يطابق مُحدد CSS.
يقارن الجدول أدناه بين طرق الاختيار الأربع الأكثر شيوعًا حتى تتمكن من اختيار الطريقة المناسبة للوظيفة.
| الأسلوب | سياسات الإرجاع والاستبدال | أفضل استخدام عند |
|---|---|---|
| getElementById | عنصر واحد | أنت تعرف المعرف الدقيق والفريد للهدف. |
| getElementsByClassName | مجموعة HTML مباشرة | أنت بحاجة إلى أن تشترك جميع العناصر في اسم فئة واحد. |
| querySelector | عنصر واحد (التطابق الأول) | تريد استخدام أي مُحدِّد CSS، وليس فقط id أو class. |
| الاستعلام | قائمة العقد الثابتة | تحتاج إلى المرور على كل تطابق باستخدام forEach. |
تقبل كل من querySelector و querySelectorAll أي مُحدِّد CSS صالح، مما يجعلهما الخيار الأمثل والأكثر مرونة للبرمجة الحديثة. جرّب المقتطف البرمجي أدناه في صفحة تحتوي على عنصر باستخدام id="title" والعديد من العناصر مع class="item":
const heading = document.getElementById("title"); const itemsByClass = document.getElementsByClassName("item"); const firstItem = document.querySelector(".item"); const allItems = document.querySelectorAll(".item"); console.log(heading.textContent, itemsByClass.length, allItems.length);
يظل getElementById و getElementsByClassName أسرع في عمليات البحث البسيطة، بينما يفضل استخدام querySelector و querySelectorAll عندما تحتاج منطق التحديد إلى قوة بناء جملة CSS الكاملة، مثل محددات السمات أو المحددات الفرعية.
كيفية تعديل وإنشاء وإزالة عناصر DOM
بمجرد تحديد عنصر ما، Javaيمكن للبرنامج النصي قراءة أو إعادة كتابة محتواه وخصائصه، وحتى وجوده في الشجرة. باستخدام DOM، Javaيمكن للبرنامج النصي إنشاء عناصر وسمات جديدة، وتغيير العناصر والسمات الموجودة، وإزالة العناصر والسمات الموجودة بالكامل.
قم بتغيير المحتوى باستخدام getElementById و innerHTML
- getElementById: للوصول إلى العناصر والسمات التي تم تعيين معرفها.
- InnerHTML: للوصول إلى محتوى العنصر.
جرب هذا المثال بنفسك:
<html> <head> <title>DOM!!!</title> </head> <body> <h1 id="one">Welcome</h1> <p>This is the welcome message.</p> <h2>Technology</h2> <p>This is the technology section.</p> <script type="text/javascript"> var text = document.getElementById("one").innerHTML; alert("The first heading is " + text); </script> </body> </html>
يؤكد مربع التنبيه أن getElementById قد حدد موقع العنوان وأن innerHTML أعاد النص المخزن بداخله.
اقرأ كل فقرة باستخدام getElementsByTagName
getElementsByTagName: للوصول إلى العناصر والسمات باستخدام اسم العلامة. هذه الطريقة سوف ترجع مجموعة لجميع العناصر التي لها نفس اسم العلامة.
جرب هذا المثال بنفسك:
<html> <head> <title>DOM!!!</title> </head> <body> <h1>Welcome</h1> <p>This is the welcome message.</p> <h2>Technology</h2> <p id="second">This is the technology section.</p> <script type="text/javascript"> var paragraphs = document.getElementsByTagName("p"); alert("Content in the second paragraph is " + paragraphs[1].innerHTML); document.getElementById("second").innerHTML = "The orginal message is changed."; </script> </body> </html>
لأن getElementsByTagName تُرجع مجموعة حية، فإن paragraphs[1] تشير إلى الفقرة الثانية في المستند، وتحديث innerHTML يؤدي على الفور إلى الكتابة فوق نصها على الشاشة.
إنشاء العناصر وإزالتها باستخدام createElement و removeChild
إلى جانب تغيير ما هو موجود بالفعل على الصفحة، يتيح لك نموذج كائن المستند (DOM) إضافة عناصر جديدة تمامًا أو إزالة العناصر الموجودة:
- إنشاء عنصر(): يقوم بإنشاء عقدة عنصر جديدة في الذاكرة.
- appendChild(): يقوم بربط عقدة كآخر عنصر فرعي لعنصر أب.
- setAttribute(): يضيف أو يُحدّث سمة، مثل
classorhref، على عنصر. - removeChild(): يزيل عقدة فرعية محددة من عقدتها الأصلية.
يقوم المثال أدناه بإنشاء عنصر قائمة جديد، وإعطائه نصًا وفئة، وإلحاقه بقائمة موجودة، ثم إزالة العنصر الأول من نفس القائمة:
const list = document.getElementById("myList"); const newItem = document.createElement("li"); newItem.textContent = "Freshly added item"; newItem.setAttribute("class", "highlight"); list.appendChild(newItem); list.removeChild(list.firstElementChild);
لا يُظهر استدعاء الدالة createElement() وحده أي شيء، لأن العقدة لا تزال موجودة في الذاكرة فقط. ولا تظهر إلا بعد أن تُلحقها الدالة appendChild()، أو دالة مشابهة مثل prepend()، في مكان ما داخل الشجرة المرئية. كما تدعم المتصفحات الحديثة دالة node.remove() المختصرة، التي تحذف العنصر مباشرةً دون الحاجة إلى مرجع إلى العنصر الأب، على عكس الصيغة القديمة parent.removeChild(node).
كيفية التعامل مع الأحداث في Javaسيناريو
الحدث هو أي إجراء يمكن للمتصفح رصده، مثل النقر أو الضغط على مفتاح أو تحميل صفحة. يمكنك إضافة معالج أحداث إلى عنصر معين بطريقتين رئيسيتين.
قم بإرفاق معالج باستخدام onclick أو addEventListener
أما الأسلوب الأول والأقدم فيقوم بتعيين دالة مباشرة لخاصية الحدث الخاص بالعنصر:
document.getElementById(id).onclick=function()
{
lines of code to be executed
}
أو باستخدام طريقة addEventListener() الحديثة والأكثر مرونة:
document.getElementById(id).addEventListener("click", functionname)
يُفضّل عمومًا استخدام الدالة `addEventListener()` لأنها تتيح لك ربط أكثر من معالج حدث واحد بنفس الحدث على نفس العنصر، كما أنها تقبل وسيطًا ثالثًا اختياريًا يتحكم في عملية الالتقاط، والذي سنتناوله لاحقًا في هذا القسم. وتتكامل هذه الدالة أيضًا مع الدالة `removeEventListener()`، التي تفصل معالج الحدث عند انتهاء الحاجة إليه، وهو أمر لا تستطيع الخاصية `onclick` القيام به بمفردها.
يدعم HTML أيضًا نمطًا ثالثًا: معالج مضمن مكتوب مباشرة على الوسم، مثل <button onclick="clicked()">Click Me</button>تخلط المعالجات المضمنة بين الترميز والمنطق، وسرعان ما يصبح صيانتها صعبًا، لذا فإن معظمها Javaيحتفظ مطورو البرامج النصية بها للعروض التوضيحية السريعة ويعتمدون على addEventListener() للتطبيقات الحقيقية.
جربها: مثال كامل لحدث النقر
جرب هذا المثال بنفسك:
<html> <head> <title>DOM!!!</title> </head> <body> <input type="button" id="btnClick" value="Click Me!!" /> <script type="text/javascript"> document.getElementById("btnClick").addEventListener("click", clicked); function clicked() { alert("You clicked me!!!"); } </script> </body> </html>
يؤدي النقر على الزر إلى تشغيل الدالة clicked()، والتي بدورها تُفعّل Javaمربع تنبيه البرنامج النصي يؤكد أن معالج الأحداث قد تم تشغيله بنجاح.
كائن الحدث
يستقبل كل معالج أحداث تلقائيًا كائن حدث كمعامله الأول. يحمل هذا الكائن تفاصيل مفيدة حول ما حدث، بما في ذلك event.target (العنصر المحدد الذي بدأ منه الإجراء)، وevent.type (اسم الحدث، مثل "click")، وأساليب مثل event.preventDefault()، التي توقف السلوك الافتراضي للمتصفح، مثل النقر على رابط أو إرسال نموذج.
document.getElementById("btnClick").addEventListener("click", function(event) { console.log("Clicked element: " + event.target.id); });
هناك خاصيتان إضافيتان تُكملان كائن الحدث: event.currentTarget يشير دائمًا إلى العنصر الذي يرتبط به المستمع، حتى لو أبلغ event.target عن عنصر فرعي متداخل، ويوقف event.stopPropagation() الحدث قبل أن يستمر في الانتشار أو الالتقاط. إلى جانب preventDefault()، تمنح هذه الأدوات المعالج تحكمًا دقيقًا في ما سيحدث لاحقًا.
الحدث/الفعالية Bubblالتسجيل، والتقاط البيانات، والتفويض
عندما يتم إطلاق حدث ما على عنصر متداخل، فإنه لا يتوقف عند هذا الحد. فقاعات في هذه المرحلة، ينتقل الحدث تصاعديًا من العنصر المستهدف عبر كل عنصر سلف، وصولًا إلى المستند. اسر في المرحلة الأولى، والتي يتم تشغيلها اختيارياً، ينتقل الحدث نزولاً من المستند إلى الهدف قبل بدء عملية الانتشار. تجاوز {capture: true} كوسيطة ثالثة للدالة addEventListener() للاستماع أثناء مرحلة الالتقاط.
وفد الحدث يستفيد هذا الأسلوب من خاصية التداخل: فبدلاً من ربط مستمع منفصل بكل عنصر فرعي، يتم ربط مستمع واحد بالعنصر الأب المشترك، ثم يتم فحص خاصية event.target لتحديد العنصر الفرعي الذي أطلق الحدث. هذا الأسلوب يستهلك ذاكرة أقل، ويغطي تلقائيًا العناصر التي تُضاف إلى الصفحة لاحقًا.
const list = document.getElementById("myList"); list.addEventListener("click", function(event) { if (event.target.tagName === "LI") { alert("You clicked " + event.target.textContent); } });
يمنحك التفويض، إلى جانب خاصية الفقاعات والتقاط البيانات، تحكمًا دقيقًا في كيفية عمل DOM والأحداث في Javaيستجيب البرنامج النصي كلما أصبحت الصفحة أكثر تفاعلية.

