ساخت و افزودن عناصر جدید به DOM

مقدمه

در فصل قبل یاد گرفتیم چگونه عناصر موجود در DOM را پیدا کنیم و بین آن‌ها حرکت کنیم. اما یکی از رایج‌ترین نیازهای واقعی، ساختن عناصر کاملاً جدید و اضافه کردن آن‌ها به صفحه است؛ مثلاً افزودن یک آیتم جدید به یک لیست، بدون این‌که از قبل در HTML نوشته شده باشد. در این درس، روش‌های استاندارد ساخت و افزودن عنصر به DOM را بررسی می‌کنیم.

createElement — ساخت یک عنصر جدید

برای ساخت یک عنصر تازه، از document.createElement استفاده می‌کنیم؛ این متد، نام یک تگ را می‌گیرد و یک عنصر جدید از آن نوع می‌سازد:

ساخت یک عنصر جدید با createElement
خروجی کنسول اینجا نمایش داده می‌شود...

تحلیل کد

نکته‌ی مهم اینجاست که newParagraph، با اینکه یک عنصر p واقعی است، هنوز در هیچ‌جای صفحه‌ی قابل مشاهده قرار نگرفته؛ فقط در حافظه ساخته شده است. اگر همین الان صفحه را باز کنیم، هیچ اثری از این عنصر نمی‌بینیم. برای این‌که این عنصر واقعاً روی صفحه ظاهر شود، باید آن را به‌طور صریح به یک نقطه‌ی مشخص از DOM Tree اضافه کنیم.

تعیین محتوا پیش از افزودن

معمولاً پیش از افزودن عنصر تازه‌ساخته‌شده به صفحه، محتوای آن را هم تعیین می‌کنیم:

let newParagraph = document.createElement("p");
newParagraph.textContent = "این یک پاراگراف تازه‌ساخته‌شده است";

appendChild — افزودن به انتهای فرزندان

متد appendChild عنصر موردنظر را به‌عنوان آخرین فرزند، به یک عنصر والد اضافه می‌کند:

افزودن عنصر جدید با appendChild
خروجی کنسول اینجا نمایش داده می‌شود...

تحلیل رفتار جاوااسکریپت

پس از اجرای appendChild، عنصر newParagraph واقعاً به انتهای فهرست فرزندان container اضافه می‌شود و بلافاصله در صفحه‌ی قابل‌مشاهده ظاهر می‌شود؛ چون DOM، همان‌طور که در فصل قبل دیدیم، نمایشی زنده از صفحه است و هر تغییری در آن، بلافاصله در رابط کاربری منعکس می‌شود.

append — روش مدرن‌تر و انعطاف‌پذیرتر

متد جدیدتر append، چند مزیت نسبت به appendChild دارد: می‌تواند چند عنصر را هم‌زمان اضافه کند، و علاوه بر عنصر، متن خام (Text) را نیز مستقیماً می‌پذیرد:

افزودن چند مورد هم‌زمان با append
خروجی کنسول اینجا نمایش داده می‌شود...

تحلیل کد

در این مثال، append هم دو عنصر span و هم یک رشته‌ی متنی خام (" - ") را در یک فراخوانی واحد، به‌ترتیب به container اضافه کرده است. این کاری است که appendChild اصلاً نمی‌تواند انجام دهد؛ چون appendChild فقط یک آرگومان می‌پذیرد و آن آرگومان هم باید حتماً یک Node باشد، نه یک رشته‌ی خام.

prepend — افزودن به ابتدای فرزندان

اگر بخواهیم عنصر جدید را به‌جای انتها، در ابتدای فهرست فرزندان قرار دهیم، از prepend استفاده می‌کنیم:

let firstItem = document.createElement("li");
firstItem.textContent = "این باید اول لیست باشد";

let list = document.getElementById("myList");
list.prepend(firstItem);

insertBefore — افزودن در یک موقعیت دقیق و مشخص

گاهی نیاز داریم عنصر جدید را نه در ابتدا و نه در انتها، بلکه دقیقاً قبل از یک عنصر مشخص دیگر قرار دهیم. برای این کار از insertBefore استفاده می‌کنیم:

افزودن عنصر در موقعیت مشخص با insertBefore
خروجی کنسول اینجا نمایش داده می‌شود...

تحلیل رفتار جاوااسکریپت

insertBefore روی والد فراخوانی می‌شود (نه روی عنصری که می‌خواهیم قبل از آن چیزی اضافه کنیم) و دو آرگومان می‌گیرد: عنصر جدید، و عنصر مرجعی که باید عنصر جدید درست قبل از آن قرار بگیرد. این متد، برخلاف append و prepend که فقط به ابتدا یا انتها محدود بودند، امکان درج در هر موقعیت دلخواهی از فهرست فرزندان را فراهم می‌کند.

افزودن عنصری که از قبل در DOM وجود دارد

نکته‌ی جالب توجه این است که اگر عنصری را که از قبل در جایی از DOM قرار دارد، دوباره با appendChild یا append به مکان دیگری اضافه کنیم، آن عنصر کپی نمی‌شود؛ بلکه از موقعیت قبلی خودش برداشته و به موقعیت جدید منتقل می‌شود:

let firstBox = document.getElementById("box1");
let secondBox = document.getElementById("box2");
let item = firstBox.firstElementChild;

secondBox.appendChild(item); // item از box1 حذف و به box2 منتقل می‌شود

اگر واقعاً نیاز به یک کپی مستقل داشته باشیم، باید از متد cloneNode استفاده کنیم که در درس‌های بعدی همین فصل بررسی می‌شود.

جدول جمع‌بندی

متدموقعیت افزودنپذیرش متن خامپذیرش چند مورد هم‌زمان
appendChildانتهای فرزندانخیرخیر
appendانتهای فرزندانبلهبله
prependابتدای فرزندانبلهبله
insertBeforeدقیقاً قبل از یک عنصر مشخصخیرخیر

جمع‌بندی

برای ساخت یک عنصر جدید از document.createElement استفاده می‌کنیم که یک عنصر خارج از DOM Tree می‌سازد و باید به‌طور صریح اضافه شود. appendChild و append برای افزودن به انتها، prepend برای افزودن به ابتدا، و insertBefore برای درج در یک موقعیت دقیق و مشخص استفاده می‌شوند. متد append نسبت به appendChild انعطاف‌پذیرتر است، چون هم متن خام و هم چند مورد را هم‌زمان می‌پذیرد.