سلام دوستان 👋 توی این پست از مجموعه پستهای ریاکت ۱۰۱ میخوایم بررسی کنیم که Virtual DOM چیه، برای چی معرفی شده و توی ریاکت چطوری کار میکنه.
Virtual DOM چیه؟ 🤔
Virtual DOM که به اختصار به اون vDOM هم گفته میشه، یک نمونهٔ بهینهسازی شده از دام واقعی (Real DOM) هست که توی حافظه نگه داشته میشه و هدف از معرفی اون افزایش سرعت و عملکرد برنامههای فرانتاندی هست. vDOM معمولاً توسط کتابخونههایی استفاده میشه که با UI سر و کار دارن. مثل ریاکت و ویو.
مشکل دام اصلی چیه؟
توی دنیای مدرن وب، توی یک صفحه ممکنه صدها تغییر و تعامل رخ بده. بنابراین Interactivity و Responsiveness (قابلیت تعامل و واکنشپذیری) اهمیت بالایی داره. اما دام واقعی و نحوهٔ کارایی اون هنوز پاسخگوی چنین نیازی نیست.
هر تغییری که توی DOM اصلی رخ میده، علاوهبر اینکه تمام اون مجدد رندر میشه، خیلی از رویدادهای دیگه رو به همراه داره. از جمله بازطراحی مجدد صفحه (Layout Repaint) توسط مرورگر برای همگام شدن با آخرین تغییرات دام. در شرایطی که بعد از هر تغییر توی دام، مرورگر بهینهسازیهایی رو انجام میده، تغییرات سریعِ کوچیک و بزرگ میتونه مرورگر رو کاملاً کند و غیر بهینه کنه. پس میبایست روشی رو اختراع کرد که بشه تغییرات توی صفحه خیلی سریع و با کمترین هزینه رخ بدن؛ طوری که برنامه بهینگی خودش رو حفظ کنه. برای همین Virtual DOM معرفی شد.
vDOM توی ریاکت چطوری کار میکنه؟
vDOM توی یک برنامهٔ ریاکتی ۴ مرحلهٔ مهم رو طی میکنه:
مرحله اول: ساختن vDOM
وقتی یک برنامهٔ ریاکتی برای اولین بار رندر میشه، یک vDOM هم از المنتهایی که باید رندر بشه ساخته میشه. این DOM یک ساختار درختی (Tree) از دام واقعی و المنتهای اون هست که در حال حاضر رندر شده.
مرحله دوم: بروزرسانی vDOM
توی ریاکت همونطور که میدونیم برنامه زمانی Re-render میشه که موارد ریاکتیو مثلاً یک State یا Prop تغییر کنن. وقتی چنین تغییری رخ میده، ریاکت قبل از اینکه تغییرات رو توی دام اصلی اعمال کنه، ابتدا vDOM رو با این تغییرات بروز میکنه.
مرحله سوم: مقایسه vDOM جدید با نسخه قبلی
توی این مرحله ریاکت طی یک الگوریتم پیچیده که به اون Reconciliation Algorithm گفته میشه، مقایسهای بین vDOM جدید با vDOM قبلی انجام میده تا دقیق بتونه تغییرات رو شناسایی کنه.
مرحله چهارم: اعمال تغییرات
حالا که تغییرات شناسایی شد، ریاکت تلاش میکنه که همهٔ تغییرات به شکل یکجا (Batch update) توی دام اصلی اعمال کنه تا کمترین تعداد Re-render اتفاق بیوفته. به این عملیات Reconciliation Process گفته میشه.
یک مثال ساده برای اینکه این مراحل رو درک کنیم:
import React, { useState, useEffect } from 'react'; function Counter() { const [count, setCount] = useState(0); useEffect(() => { console.log('count:', count); }, [count]); const handleClick = () => { setCount(count + 1); setCount(count + 2); setCount(count + 3); }; return ( <div> <p>Count: {count}</p> <button onClick={handleClick}>Increment</button> </div> ); } export default Counter;
اینجا وقتی روی دکمه توی خط ۱۹ کلیک میکنیم، تابع handleClick اجرا میشه و مقدار counter رو از صفر به ۱، ۲ و نهایتاً به ۳ میرسونه. با توجه به اینکه مقدار استیت سه بار داره تغییر میکنه، شاید انتظار داریم که توی کنسول (کد خط ۷) هر سه تغییر رو ببینیم. یعنی سه بار رندر. اما باید بدونیم که طبق الگوریتم Reconciliation و مکانیزم Batch update، رندر فقط یک بار اتفاق میافته و توی کنسول فقط یک عدد ۳ نمایش داده میشه (بدون اینکه عددهای ۱ و ۲ نمایش داده بشن.)
این الگوریتم صبر میکنه تا همهٔ تغییرات توی بازه زمانی مشخص اتفاق بیوفته و بعد تغییرات رو توی دام اصلی اعمال میکنه. با این اتفاق، از رخدادن تعداد زیادی از رندرهای اضافی جلوگیری میشه، دام اصلی کمترین و بهینهترین تغییرات رو میپذیره، که در نتیجه برنامهٔ ما خیلی سریعتر و واکنشپذیرتر خواهد بود.
خب دوستان امیدوارم از اطلاعاتی که بررسی کردیم استفاده کرده باشین. روزتون خوش 👋
