آشنایی با DOM و ساختار درختی صفحه

مقدمه

تا اینجای این دوره، تقریباً تمام تمرکز ما روی خودِ زبان جاوااسکریپت بود؛ متغیرها، توابع، Scope، Closure، this و Object Model. از این فصل به بعد، وارد بخشی از جاوااسکریپت می‌شویم که مستقیماً با مرورگر و صفحه‌ی وب در ارتباط است. اولین و مهم‌ترین مفهوم این بخش، DOM است؛ پلی که جاوااسکریپت را به محتوای واقعی صفحه‌ی HTML متصل می‌کند.

DOM چیست؟

DOM مخفف Document Object Model است. وقتی مرورگر یک فایل HTML را بارگذاری می‌کند، آن را صرفاً به‌عنوان متن نگه نمی‌دارد؛ بلکه آن را به یک ساختار داده‌ای زنده و قابل‌دسترسی از طریق جاوااسکریپت تبدیل می‌کند. این ساختار، DOM نام دارد و به ما اجازه می‌دهد با کد جاوااسکریپت، محتوای صفحه را بخوانیم، تغییر دهیم، عناصر جدید اضافه کنیم یا عناصر موجود را حذف کنیم.

نکته‌ی مهم این است که DOM بخشی از خودِ زبان جاوااسکریپت نیست؛ بلکه یک Browser API است که مرورگر آن را در اختیار جاوااسکریپت قرار می‌دهد. به همین دلیل، DOM در محیط‌هایی که جاوااسکریپت بدون مرورگر اجرا می‌شود (مثل Node.js) به‌طور پیش‌فرض وجود ندارد.

از HTML تا DOM

فرض کنید این HTML ساده را داشته باشیم:

<body>
  <h1>عنوان صفحه</h1>
  <p>یک پاراگراف ساده</p>
</body>

مرورگر این کد را می‌خواند و آن را به یک ساختار درختی از اشیاء تبدیل می‌کند؛ هر تگ HTML، به یک Node (گره) در این درخت تبدیل می‌شود. body یک Node است، h1 فرزند آن است، و p نیز فرزند دیگری از body است.

DOM Tree — ساختار درختی صفحه

به این ساختار سلسله‌مراتبی از Node ها، DOM Tree می‌گویند؛ چون دقیقاً مثل یک درخت، از یک ریشه شروع می‌شود و به شاخه‌ها و برگ‌ها تقسیم می‌شود. ریشه‌ی این درخت، شیئی به نام document است که از طریق جاوااسکریپت همیشه در دسترس است:

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

تحلیل کد

document شیئی است که کل صفحه‌ی HTML جاری را در قالب DOM Tree نمایندگی می‌کند. document.body مستقیماً به Node مربوط به تگ <body> صفحه اشاره می‌کند. هر Node در این درخت، خودش می‌تواند Property هایی داشته باشد که به فرزندان، والد، یا محتوای آن اشاره می‌کنند؛ این ارتباطات دقیقاً همان چیزی است که در درس بعدی، تحت عنوان Traversing DOM، با جزئیات کامل بررسی می‌کنیم.

سلسله‌مراتب کلی یک DOM Tree

یک نمای ساده از سلسله‌مراتب DOM Tree برای یک صفحه‌ی معمولی به این شکل است:

document
  └── html
      ├── head
      │   └── title
      └── body
          ├── h1
          └── p

در این ساختار، document ریشه‌ی کل درخت است. html فرزند مستقیم document است. head و body هر دو فرزند html هستند و خواهر و برادر (Sibling) یکدیگر محسوب می‌شوند. h1 و p نیز فرزندان body و خواهر و برادر یکدیگرند.

DOM با HTML یکی نیست

نکته‌ی مهمی که باید از همین ابتدا روشن شود: DOM، خودِ فایل HTML نیست؛ بلکه نمایشی زنده و در حافظه از آن است. این تفاوت اهمیت عملی زیادی دارد:

تغییر DOM هیچ تأثیری روی فایل HTML اصلی ندارد
خروجی کنسول اینجا نمایش داده می‌شود...

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

وقتی document.body.innerHTML را تغییر می‌دهیم، محتوای واقعی که کاربر در مرورگر می‌بیند فوراً تغییر می‌کند؛ اما فایل HTML اصلی روی سرور یا دیسک، دست‌نخورده باقی می‌ماند. این تغییر فقط در DOM Tree موجود در حافظه‌ی مرورگر رخ می‌دهد؛ اگر کاربر صفحه را رفرش کند، دوباره همان HTML اصلی از سرور بارگذاری و DOM از نو ساخته می‌شود. جزئیات کامل کار با innerHTML و روش‌های مشابه را در درس‌های بعدی همین فصل بررسی خواهیم کرد.

چرا DOM یک شیء (Object) است؟

نام کامل DOM، یعنی Document Object Model، به همین ویژگی اشاره دارد: مرورگر، ساختار سند HTML را در قالب اشیاء جاوااسکریپتی مدل‌سازی می‌کند. هر Node در این درخت، یک شیء با Property ها و متدهای مخصوص به خودش است؛ دقیقاً همان مفهومی که در فصل‌های اولیه‌ی این دوره، درباره‌ی Object یاد گرفتیم، حالا در قالب یک ساختار واقعی و کاربردی به کار گرفته می‌شود.

جمع‌بندی

DOM (Document Object Model) نمایشی زنده و ساختاریافته از سند HTML است که مرورگر آن را در قالب یک ساختار درختی از اشیاء (DOM Tree) در اختیار جاوااسکریپت قرار می‌دهد. هر تگ HTML به یک Node در این درخت تبدیل می‌شود؛ document ریشه‌ی این درخت است. تغییراتی که از طریق جاوااسکریپت روی DOM اعمال می‌شود، بلافاصله در صفحه‌ی نمایش‌داده‌شده منعکس می‌شود، اما هرگز فایل HTML اصلی را تغییر نمی‌دهد.