همه ما درباره DOM یا Document Object Model (طرح آبجکت سند) شنیدهایم، که هر از گاهی به آن اشاره میشود و به JavaScript مربوط است. DOM در توسعهدهی وب یک مفهوم بسیار مهم است. بدون آن، ما نمیتوانیم صفحات HTML را به صورت دینامیک در مرورگر تغییر دهیم.
یادگیری و درک DOM، به راههای بهتری برای دسترسی، تغییر دادن و بازرسی عناصر مختلف یک صفحه HTML ختم میشود. طرح آبجکت سند هم ممکن است در کاهش دادن تکثیرهای غیر ضروری در زمان اجرای اسکریپت کمک کند.
قبل از این که ادامه دهیم، توجه کنید که این آموزش بر پایه زبان JavaScript میباشد که دوره آموزشی مربوطه بر روی راکت را میتوانید در این لینک بیابید.
ساختارهای درختی داده
قبل از این که درباره ماهیت DOM، نحوه وجود آن و اتفاقاتی که درون آن میفتند صحبت کنیم، میخواهم که درباره ساختارهای درختی بدانید. نه انواع مخروطی و برگریز آنها، بلکه درباره ساختارهای درختی داده.
اگر ما تعریف ساختارهای داده را سادهسازی کنیم، درک مفهوم آن بسیار سادهتر میشود. من میگویم که یک ساختار داده، درباره ترتیببندی دادههای شماست. بله، فقط همان ترتیببندی قدیمی، همانطور که لوازم خانه خود را در خانه خود، کتابها را در یک قفسه کتاب و تمام انواع مختلف غذا را در بشقاب خود ترتیببندی میکنید تا آنها را برای خود معنادار کنید.
البته، ساختار داده در اینجا محدود نمیشود، این تقریبا چیزی است که همه چیز از آن آغاز میشود. این «ترتیببندی» در قلب همه چیز قرار دارد. این ترتیببندی برای DOM هم مهم است. اما ما هنوز درباره DOM صحبت نمیکنیم، پس بگذارید شما را به سمت یک ساختار داده که ممکن است با آن آشنا باشید منحرف کنم: آرایهها.
آرایهها و ساختارهای درختی
آرایهها، دارای شاخص و طول میباشند، میتوانند چند بعدی باشند و بسیاری مشخصات دیگر هم دارند. هر چقدر هم که دانستن این موارد درباره آرایهها مهم باشد، اما بیایید حال خود را درگیر آنها نکنیم. برای ما، یک آرایه بسیار ساده است. آرایه وقتی است که شما چیزهای مختلف را در یک صف، ترتیببندی میکنید.
به طور مشابه، وقتی که درباره ساختارهای درختی فکر میکنید، بیایید فرض کنیم که مسئله قرار دادن چند چیز زیر یکدیگر است، که فقط با یک مورد در بالا شروع میشود.
حال، شما میتوانید خط اردکها در بالا را بردارید، آن را عمودی کنید، و بگویید: «حال همه اردکها زیر یک اردک دیگر هستند.» پس آیا این یک ساختار درختی است؟ بله.
بسته به ماهیت دادههای شما و نحوه استفاده شما از آنها، بالاترین داده در ساختار درختی شما (که ریشه (root) نام دارد) ممکن است چیزی با اهمیت بالا بوده، یا چیزی باشد که فقط با هدف بستن عناصر دیگر در زیر خود وجود دارد.
در هر صورت، بالاترین عنصر در یک ساختار درختی داده، کاری بسیار مهم را انجام میدهد. این عنصر جایی را فراهم میکند که بتوانید برای هر اطلاعاتی که میخواهید در ساختار درختی مورد نظر پیدا کنید، از آن شروع به جستجو کنید.
معنای DOM
DOM مخفف Document Object Model (طرح آبجکت سند) میباشد. سند (Document)، به یک سند HTML (XML) اشاره دارد که به عنوان یک آبجکت نمایش داده میشود. (در JavaScript همه چیز فقط میتواند به عنوان یک آبجکت نمایش داده شود!)
طرح (Model)، توسط مرورگری که یک سند HTML را میگیرد و یک آبجکت میسازد که آن را نمایش میدهد، ساخته میشود. ما میتوانیم با استفاده از JavaScript به این آبجکت دسترسی داشته باشیم. و از آنجایی که ما از این آبجکت برای دستکاری سند HTML و ساخت برنامه خود استفاده میکنیم، DOM اساسا یک API است.
ساختار درختی DOM
در کد JavaScript، سند HTML به عنوان یک آبجکت نمایش داده میشود. تمام دادههایی که از سند خوانده شدهاند هم به عنوان چند آبجکت ذخیره میشوند، که زیر یکدیگر قرار دارند. (زیرا همانطور که پیشتر گفتم، در JavaScript همه چیز فقط میتواند به عنوان یک آبجکت نمایش داده شود)
پس این اساسا ترتیببندی فیزیکی داده DOM در کد است: همه چیز به عنوان آبجکت ترتیببندی میشود. گرچه از نظر منطقی، این یک ساختار درختی است.
Parse کننده DOM
هر نرمافزار مرورگر، یک برنامه به عنوان DOM Parser دارد که مسئول parse کرن یک سند HTML به DOM است.
مرورگر یک صفحه HTML را میخواند و دادههای آن را تبدیل به آبجکتهایی میکند که DOM را تشکیل میدهند. اطلاعات حاضر در این آبجکتهای DOM جاوااسکریپت، از نظر منطقی به عنوان یک ساختار درختی داده ترتیببندی شدهاند که به عنوان ساختار درختی DOM شناخته میشود.
Parse کردن داده از HTML به ساختار درختی DOM
یک فایل HTML نمونه را در نظر داشته باشید. این فایل، عنصر ریشه <html> را دارد. عناصر زیرین آن، <head> و <body> هستند، که هر کدام تعداد زیادی عنصر فرزند مختص خود دارند.
پس اساسا، مرورگر دادههای موجود در سند HTML که چیزی مشابه این مورد هستند را میخواند:
<html>
<head>
<meta/>
<link/>
</head>
<body>
<header>
<h1></h1>
<h2></h2>
</header>
<main>
<article>
<p></p>
<p></p>
<p></p>
</article>
</main>
<footer>
<div></div>
</footer>
</body>
</html>
و آن را به یک ساختار درختی DOM به این صورت ترتیببندی میکند:
نمایش هر عنصر HTML (و محتویات متعلق به آن) در ساختار درختی DOM، به عنوان یک گره (Node) شناخته میشود. گره ریشه، گره <html> میباشد.
رابط DOM در JavaScript، سند (document) نام دارد (زیرا نمایانگر سند HTML است). از این رو، ما از طریق یک رابط document به ساختار درختی DOM دسترسی مییابیم.
ما نه تنها میتوانیم از طریق DOM به سند HTML دسترسی داشته باشیم، بلکه میتوانیم آن را دستکاری هم بنماییم. ما میتوانیم عناصری را به یک صفحه وب اضافه کنیم، آنها را حذف کرده یا بروزرسانی کنیم. هر زمان که ما یک گره را در ساختار درختی DOM تغییر داده، یا بروزرسانی میکنیم، نتیجه این کار بر روی صفحه وب منعکس میشود.
نحوه طراحی شدن گرهها (nodeها)
پیشتر اشاره کردم که هر قطعه از یک سند HTML در JavaScript، به عنوان یک آبجکت ذخیره میشود. پس دادههای ذخیره شده به عنوان یک آبجکت، چگونه میتوانند به عنوان یک ساختار درختی ذخیره شوند؟
گرههای یک ساختار درختی DOM، مشخصات یا ویژگیهای مشخصی دارند. تقریبا تمام گرهها در یک ساختار درختی، یک گره والد (گرهای که دقیقا بالای آنها قرار دارد)، چند گره فرزند (گرههایی که زیر آنها قرار دارند) و چند گره برادر (گرههای دیگر که به والد مشابه تعلق دارند) را دارند. داشتن این خانواده در بالا، پایین و اطراف یک گره، چیزی است که باعث میشود آن گره واجد شرایط بخشی از یک ساختار درختی بودن باشد.
این اطلاعات خانواده هر گره، به عنوان ویژگیهای آن در آبجکتی که نمایانگر آن گره است ذخیره میشود. برای مثال، children یک ویژگی از گرهای است که لیستی از عناصر فرزند آن گره را حمل میکند، و از این رو از نظر منطقی، children عناصر فرزند خود را زیر گره مورد نظر ترتیببندی میکند.
از دستکاری بیش از حد DOM خودداری کنید
هر چقدر هم که بروزرسانی DOM برایمان کاربردی باشد (در جهت تغییر یک صفحه وب)، همچنان ممکن است که آن را بیش از حد انجام دهیم.
فرض کنید که میخواهید رنگ یک <div> را بر روی یک صفحه با استفاده از JavaScript تغییر دهید. کاری که باید انجام دهید، این است که به آبجکت گره DOM متناظر آن دسترسی داشته باشید و ویژگی رنگ را بروزرسانی کنید. این مسئله نباید باقی ساختار درختی (گرههای دیگر موجود در آن ساختار درختی) را تحت تاثیر قرار دهد.
اما اگر بخواهید یک گره را از یک ساختار درختی حذف کنید، یا این که یک گره دیگر اضافه کنید چه؟ شاید نیاز باشد که کل ساختار درختی با گره حذف شده یا اضافه شده به آن، مجددا ترتیببندی شود. این یک کار پر هزینه است و برای به انجام رسیدن، نیازمند زمان و منابع مرورگر میباشد.
برای مثال فرض کنید که میخواهید ۵ ردیف دیگر به یک جدول اضافه کنید. ساختار درختی مورد نظر برای هر ردیف، وقتی که گرههای جدیدش ساخته شدهاند و به DOM اضافه شدهاند، بروزرسانی میشود که در مجموع پنج بار میباشد.
ما میتوانیم با استفاده از رابط DocumentFragment از این مسئله جلوگیری کنیم. به آن به عنوان جعبهای فکر کنید که میتواند تمام پنج ردیف را در خود نگه دارد و به ساختار درختی مورد نظر اضافه شود. به این صورت پنج ردیف مورد نظر به عنوان یک تکه داده تکی اضافه میشوند، نه به صورت یک به یک، که در نتیجه به یک بروزرسانی ختم میشود.
این مسئله فقط وقتی که ما عناصر را حذف کرده یا اضافه میکنیم پیش نمیآیند، بلکه وقتی که یک عنصر را تغییر اندازه میدهید هم اتفاق میافتد. پس گرههای متناظر تمام عناصر دیگر باید بروزرسانی شوند و عناصر HTML هم مجددا با توجه به قوانین جدید رندر خواهند شد.
به طور مشابه، وقتی که طرح یک صفحه وب به عنوان یک طرح کلی تحت تاثیر قرار میگیرد، یک بخش از صفحه وب یا کل آن ممکن است نیاز به رندر مجدد داشته باشند. این روند به عنوان یک Reflow شناخته میشود. در جهت خودداری از reflow بیش از حد، مطمئن شوید که شما DOM را بیش از حد تغییر نمیدهید. تغییرات اعمال شده به DOM، تنها چیزی نیست که میتواند از Reflow بر روی یک صفحه وب مجددا استفاده کند. بسته به مرورگر، برخی فاکتورهای دیگر هم میتوانند در آن شرکت کنند.
جمعبندی
اگر بخواهیم همه چیز را جمعبندی کنیم، DOM به عنوان یک ساختار درختی متشکل از تمام عناصر یافت شده در سند HTML، بصریسازی شده است. از نظر فیزیکی (هر چقدر که یک چیز دیجیتال میتواند فیزیکی شود)، DOM مجموعهای از آبجکتهای JavaScript تو در تو است که ویژگیهای و متدهایشان اطلاعاتی را نگه میداند که ترتیببندی آنها در قالب یک ساختار درختی را از نظر منطقی ممکن میکنند.
دیدگاه و پرسش
در حال دریافت نظرات از سرور، لطفا منتظر بمانید
در حال دریافت نظرات از سرور، لطفا منتظر بمانید