Virtual DOM چیست؟ — به زبان ساده
DOM مجازی یا «Virtual DOM» نوعی مفهوم بسیار مهم در فریمورک «React» است. کسانی که با این فریمورک جاوا اسکریپت کار کرده باشند، احتمالاً با این اصطلاح برخورد کردهاند. با این حال، ممکن است مفهوم اینکه Virtual DOM چیست و چرا React از آن استفاده میکند هنوز برایشان مبهم باشد. در این مطلب از «مجله فرادرس» در رابطه با اینکه Virtual DOM چیست و در زبان برنامه نویسی جاوا اسکریپت و فریمورک React این مفهوم به چه معناست، توضیحاتی ارائه شده است.
React DOM چیست؟
قبل از اینکه به بررسی اینکه Virtual DOM چیست بپردازیم، آشنایی با DOM مرورگر به عنوان نوعی پیشنیاز یادگیری آن خالی از لطف نیست. هنگامی که کاربری از صفحه وب بازدید میکند، مرورگر نوعی سند HTML را از سرور دریافت کرده و سپس نوعی ساختار درخت مانند به نام «Document Object Model (DOM)» از آن HTML ایجاد خواهد کرد. این DOM ساختار صفحه وب را به صورت گرهها و اشیا نشان میدهد.
DOM به جاوا اسکریپت و سایر زبانهای برنامه نویسی اجازه میدهد تا با محتوای صفحه وب تعامل داشته باشند و آن را تغییر دهند. توسعهدهندگان میتوانند از DOM برای افزودن یا حذف عناصر، تغییر ظاهر آنها و فعال کردن تعاملات کاربر در صفحه وب استفاده کنند. اساساً DOM در جاوا اسکریپت به عنوان پلی بین سند وب و زبانهای برنامه نویسی عمل میکند.
چگونه رندرینگ مجدد بر عملکرد تأثیر می گذارد؟
بهروزرسانی DOM معمولاً فرآیندی سریع و سبک است ولی هنگامی که تغییراتی در دادههای برنامه رخ میدهد در نتیجه نیاز به بارگذاری مجدد یا رندرینگ مجدد صفحه پیدا میشود و این میتواند بر عملکرد کلی تأثیر بگذارد و زمان تاخیر را افزایش دهد. بیایید سناریویی را تصور کنیم که در آن رندر مجدد صفحه با استفاده از کد جاوا اسکریپت زیر شبیهسازی شده است:
1const update = () => {
2 const element = `
3 <h3>JavaScript:</h3>
4 <form>
5 <input type="text"/>
6 </form>
7 <span>Time: ${new Date().toLocaleTimeString()}</span>
8 `;
9
10 document.getElementById("root1").innerHTML = element;
11};
12
13setInterval(update, 1000);
در کد بالا، تابع update هر ثانیه فراخوانی میشود تا محتوای عنصری با شناسه root1 در DOM بهروز شود. این تابع هر بار نوعی ساختار HTML جدید، از جمله زمان فعلی تولید میکند.
در حالی که DOM خود را به سرعت بهروز میکند، جایگزینی مداوم محتوای HTML میتواند از نظر محاسباتی گران تمام شود، به خصوص اگر محاسبات پیچیده یا مقادیر زیادی داده در آن وجود داشته باشد. این میتواند منجر به مشکلات عملکردی مانند تاخیر یا زمان پاسخ کند شود. ساختار درختی DOM که سند را نشان میدهد به شکل زیر است:
تابع setInterval() در کد بالا به کاربر امکان میدهد هر ثانیه یک بهروزرسانی رابط کاربری را شبیهسازی کند. در تصویر خروجی زیر، میتوان مشاهده کرد که عناصر DOM سند با هر بهروزرسانی بازسازی و ترسیم میشوند. متأسفانه، این رندر مکرر باعث میشود که ورودی متن در رابط کاربری حالت فعلی خود را از دست بدهد.
همانطور که در مثال فوق نشان داده شده است، وقتی رابط کاربری بهروز میشود، فیلد متن مقدار ورودی خود را از دست میدهد که نشان دهنده نیاز به بهینهسازی است. فریمورکهای جاوا اسکریپت راهحلها و رویکردهای مختلفی را برای بهبود عملکرد رندر مجدد ارائه میدهند. با این حال، React با استفاده از چیزی به نام DOM مجازی این مشکل را برطرف میکند که در ادامه با اینکه Virtual DOM چیست آشنا خواهیم شد.
Virtual DOM چیست ؟
DOM مجازی در React نوعی کپی سبک از DOM واقعی محسوب میشود که به عنوان اشیا نشان داده شده است. این نوع DOM مستقیماً در مرورگر کاربر نمایش داده نمیشود اما در حافظه مرورگر ذخیره خواهد شد. این مفهوم در سایر فریمورکهای فرانتاند مانند «Vue» نیز استفاده میشود. با این حال، رویکرد React به «برنامه نویسی اعلانی» (Declarative Programming) آن است که آن را از سایر فریمورکها متمایز میکند. در بخش بعد به بررسی اینکه تفاوت DOM واقعی با Virtual DOM چیست پرداخته خواهد شد.
تفاوت DOM حقیقی با Virtual DOM چیست ؟
تصوری غلط و رایج وجود دارد که «DOM مجازی» (Virtual DOM) سریعتر از «DOM واقعی» (Real Dom) است یا با آن رقابت میکند، اما این درست نیست. در واقعیت، DOM مجازی در کنار DOM واقعی کار کرده و از عملیات آن پشتیبانی میکند. DOM مجازی در اصل روشی را برای DOM واقعی فراهم خواهد کرد تا در هنگام بهروزرسانی UI حداقل عملیات را انجام دهد.
در این جا مسئله اینکه تفاوت DOM واقعی با Virtual DOM چیست در قالب مثالی ساده بیان میگردد. در DOM واقعی، وقتی عنصری تغییر میکند، DOM آن عنصر و همه فرزندانش را دوباره نمایش میدهد. این رویکرد در هنگام برخورد با برنامههای کاربردی وب پیچیده که دارای تغییرات مکرر حالت و تعامل هستند، کند و ناکارآمد است. React رویکرد متفاوتی دارد. این فریمورک از DOM مجازی به عنوان نوعی واسطه در طول فرآیند رندر استفاده میکند. به جای دستکاری DOM به صورت دستی، میتوان با استفاده از رویکرد اعلامی React وضعیت مورد نظر UI را مشخص کرد.
پس از بهروزرسانی DOM مجازی، React آن را با «تصویر فوری» (اسنپشات | Snapshot) قبلی مقایسه کرده و عناصر تغییر یافته را شناسایی میکند. سپس فقط آن عناصر خاص را در DOM واقعی بهروز خواهد کرد و عملکرد را بهینه میکند. این یکی از راههایی است که DOM مجازی کارایی را بهبود میبخشد.
- نکته: Snapshot نوعی فایل پیکربندی است که سبک کامپوننت، UI و غیره را در برنامه ریاکت تعریف خواهد کرد.
با انتزاع دستکاری دستی DOM ،DOM مجازی به توسعهدهندگان این امکان را میدهد که کدهای قابل پیشبینیتر و تمیزتری بنویسند و بر ایجاد «کامپوننت» (اجزا | Components) تمرکز کنند. با DOM مجازی، کاربر لازم نیست نگران انتقال حالت باشد. هنگامی که وضعیت بهروز میشود، React تضمین خواهد کرد که DOM آن حالت را به طور دقیق منعکس میکند. در مثال قبلی، React فقط عنصر Time را در DOM واقعی در طول هر رندر مجدد بهروز میکند و مقدار فیلد ورودی را بدون هیچ ضرری حفظ خواهد کرد.
شی Virtual DOM چیست ؟
برای درک اینکه شی Virtual DOM چیست بیایید کد رندر زیر را که نشان دهنده نسخه React نمونه مثال جاوا اسکریپت قبلی است در نظر بگیریم:
1// ...
2const update = () => {
3 const element = (
4 <>
5 <h3>React:</h3>
6 <form>
7 <input type="text" />
8 </form>
9 <span>Time: {new Date().toLocaleTimeString()}</span>
10 </>
11 );
12 root.render(element);
13};
در کد بالا، نوعی تابع بهروزرسانی یا update وجود دارد که عنصر React را به نمایندگی از UI تولید میکند. این عنصر با استفاده از دستور «JSX» ایجاد میشود که روشی مختصرتر برای نوشتن کد React است. با این حال، همانطور که در زیر نشان داده شده است، می توان کد معادل را در React به صورت سادهتر نیز نوشت:
1const element = React.createElement(
2 React.Fragment,
3 null,
4 React.createElement("h3", null, "React:"),
5 React.createElement(
6 "form",
7 null,
8 React.createElement("input", {
9 type: "text"
10 })
11 ),
12 React.createElement("span", null, "Time: ", new Date().toLocaleTimeString())
13);
اگر شی element در کنسول وارد شود، چیزی شبیه به تصویر ارائه شده در پایین مشاهده خواهد شد. شیئی که در کنسول مشاهده میشود نشان دهنده DOM مجازی است. این کار به عنوان نمایشی از رابط کاربری در React عمل میکند.
1 const element = (
2 <>
3 <h3>React:</h3>
4 <form>
5 <input type="text" />
6 </form>
7 <span>Time: {new Date().toLocaleTimeString()}</span>
8 </>
9 );
10 console.log(element)
خروجی در کنسول به صورت زیر خواهد بود:
نحوه پیاده سازی DOM مجازی به وسیله React چگونه است؟
برای درک اینکه React چگونه از DOM مجازی استفاده میکند، باید دو مرحله مهم یعنی «رندرینگ | Rendering» و «اصلاح | Reconciliation» را درک کرد. در مرحله رندر، زمانی که رابط کاربری در برنامه ایجاد میشود، React نوعی درخت DOM مجازی میسازد که نمایانگر UI است. این درخت DOM مجازی در حافظه ذخیره میشود. در بهروزرسانیهای بعدی، زمانی که دادههای اساسی که برنامه را هدایت میکند تغییر مییابد، React به طور خودکار نوعی درخت DOM مجازی جدید برای بهروزرسانی ایجاد میکند.
برای تجسم این فرآیند، میتوان DOM مجازی را به شکل زیر نمایش داد:
تصویر سمت چپ، رندر اولیه DOM مجازی را نشان میدهد. همانطور که در سمت راست نشان داده شده است اگر Time تغییر کند، React نوعی درخت DOM مجازی جدید با گره بهروز شده ایجاد میکند.
توجه به این نکته مهم است که DOM مجازی به سادگی شیئی بوده که ساختار UI را نشان خواهد داد. در واقع Virtual DOM مستقیماً چیزی را روی صفحه نمایش نمیدهد. هنگامی که React درخت DOM مجازی جدید را تولید میکند، آن را با استفاده از فرآیندی به نام Reconciliation با اسنپشات قبلی مقایسه خواهد کرد. این Reconciliation شامل نوعی الگوریتم متفاوت است که تعیین میکند چه تغییراتی مورد نیاز خواهد بود.
پس از فرآیند نام برده شده، React از نوعی کتابخانه رندر مانند «ReactDOM» استفاده میکند. این کتابخانه اطلاعات را از فرآیند «تفاوت» (Diff) میگیرد و برنامه رندر شده را بر اساس آن بهروز میکند. رندر تضمین خواهد کرد که DOM واقعی فقط گرههای خاصی را که بهروز شدهاند دریافت و دوباره رنگ کرده و فرآیند رندر را بهینه میکند.
همانطور که در تصویر بالا مشاهده میشود، تنها گرهی که اطلاعات آن تغییر میکند در DOM واقعی دوباره رنگ میشود. تصویر متحرک زیر این گفته را ثابت میکند: