برای توضیح دقیقتر و جامعتر تفاوت بین Synthetic Events و Native Events در React، بیایم این دو مفهوم رو با جزئیات، مثالهای عملی، و دلایل استفاده React از Synthetic Events بررسی کنیم. هدف اینه که کاملاً روشن بشه این دو نوع رویداد چطور کار میکنن، چرا React از Synthetic Events استفاده میکنه، و چه مزیتهایی دارن.
Native Events رویدادهای خالصی هستن که مستقیماً توسط مرورگر (Browser DOM) تولید و مدیریت میشن. این رویدادها بخشی از API استاندارد DOM هستن و بستگی به مرورگر دارن (مثل Chrome، Firefox، یا Safari). هر مرورگر ممکنه این رویدادها رو کمی متفاوت پیادهسازی کنه، که میتونه باعث مشکلات سازگاری (cross-browser inconsistencies) بشه.
مستقیماً به DOM واقعی وصلن و با دستوراتی مثل addEventListener مدیریت میشن.
رفتارشون بستگی به مرورگر داره، مثلاً نحوه مدیریت event.preventDefault یا ویژگیهای event ممکنه تو مرورگرهای مختلف فرق کنه.
مثال: رویدادهایی مثل click, input, keydown که مستقیماً تو DOM فعال میشن.
javascript
const button = document.getElementById('myButton'); button.addEventListener('click', (event) => { console.log('رویداد کلیک:', event); console.log('نوع رویداد:', event.type); // 'click' console.log('هدف:', event.target); // <button id="myButton"> });
توضیح:
اینجا یه رویداد click مستقیماً به یه عنصر DOM وصل شده.
شیء event که دریافت میشه، یه شیء Native Eventه که مرورگر تولید کرده.
رفتار این رویداد ممکنه تو مرورگرهای مختلف (مثلاً Internet Explorer قدیمی) کمی متفاوت باشه.
Synthetic Events یه لایه انتزاعی (abstraction) هستن که React روی Native Events ساخته. به جای اینکه مستقیماً با رویدادهای مرورگر کار کنی، React یه نسخه استانداردشده و یکپارچه از رویدادها رو ارائه میده که رفتارشون تو همه مرورگرها یکسانه. این رویدادها به صورت wrapper دور Native Events ساخته میشن.
React یه شیء SyntheticEvent تولید میکنه که شبیه Native Eventه، ولی رفتارش استاندارد و cross-browserه.
به جای اتصال مستقیم رویدادها به عناصر DOM، React یه سیستم رویداد مرکزی (event delegation) تو ریشه اپلیکیشن (root element) پیادهسازی میکنه.
ویژگیهای استاندارد DOM (مثل event.target, event.preventDefault, event.stopPropagation) رو پشتیبانی میکنه، ولی با یه API یکپارچه.
javascript
function Button() { const handleClick = (event) => { console.log('رویداد کلیک:', event); console.log('نوع رویداد:', event.type); // 'click' console.log('هدف:', event.target); // <button> event.preventDefault(); // کار میکنه، مثل Native Event }; return <button ={handleClick}>کلیک کن</button>; }
توضیح:
اینجا یه Synthetic Eventه که React مدیریتش میکنه.
شیء event که به handleClick پاس داده میشه، یه نمونه از SyntheticEventه که React ساخته.
این شیء ویژگیهای مشابه Native Event (مثل target, type, preventDefault) داره، ولی React تضمین میکنه که رفتارش تو همه مرورگرها یکسانه.
React یه سیستم رویداد مرکزی و بهینه برای مدیریت Synthetic Events پیادهسازی کرده:
Event Delegation (نمایندگی رویدادها):
به جای اینکه رویدادها رو مستقیماً به هر عنصر DOM وصل کنه (مثل element.addEventListener)، React همه رویدادها رو به یه ریشه مرکزی (معمولاً document یا container اصلی اپلیکیشن) وصل میکنه.
وقتی یه رویداد (مثل کلیک) تو DOM رخ میده، React اون رو میگیره، یه SyntheticEvent میسازه، و بر اساس ساختار Virtual DOM تشخیص میده کدوم کامپوننت باید این رویداد رو دریافت کنه.
Pooling (استخر رویدادها):
برای بهینهسازی عملکرد، React از یه Event Pool استفاده میکنه. یعنی شیءهای SyntheticEvent بعد از استفاده بازیافت میشن و دوباره استفاده میشن.
به همین دلیل، اگه بخوای یه SyntheticEvent رو بعد از اتمام تابع نگه داری (مثلاً تو یه setTimeout)، باید از event.persist() استفاده کنی، وگرنه ویژگیهای رویداد null میشن.
مثال:
javascript
function Button() { const handleClick = (event) => { event.persist(); // نگه داشتن رویداد setTimeout(() => { console.log(event.type); // بدون persist، این خط خطا میده }, 1000); }; return <button ={handleClick}>کلیک کن</button>; }
Cross-Browser Consistency:
React تفاوتهای بین مرورگرها (مثل نحوه مدیریت رویدادهای خاص تو Safari در مقابل Chrome) رو استاندارد میکنه. مثلاً:
اطمینان میده event.preventDefault() تو همه مرورگرها به یه شکل کار میکنه.
ویژگیهایی مثل event.target یا event.currentTarget همیشه رفتار قابلپیشبینی دارن.
ویژگیSynthetic Events (React)Native Events (مرورگر)مدیریتتوسط React مدیریت میشهمستقیماً توسط مرورگر مدیریت میشهسازگاری مرورگرهاکاملاً cross-browser و یکپارچهممکنه تو مرورگرهای مختلف متفاوت باشهاتصال رویداداز طریق event delegation به ریشه اپلیکیشنمستقیماً به عناصر DOM با addEventListenerبهینهسازیاستفاده از event pooling و Virtual DOMبدون بهینهسازی داخلیدسترسی به شیء رویدادمحدود به scope تابع (نیاز به persist)همیشه در دسترسهمثالonClick={handleClick}element.addEventListener('click', ...)
React به دلایل زیر از Synthetic Events به جای Native Events استفاده میکنه:
Cross-Browser Consistency (سازگاری بین مرورگرها):
مرورگرهای مختلف (مثل Chrome، Firefox، یا Edge) ممکنه رویدادها رو به شکلهای کمی متفاوت مدیریت کنن. Synthetic Events یه API یکپارچه ارائه میدن که تو همه مرورگرها رفتار یکسانی داره.
بهینهسازی عملکرد:
Event Delegation: به جای اضافه کردن listener به هر عنصر DOM، React یه listener مرکزی تو ریشه اپلیکیشن (root) داره. این کار تعداد listenerها رو کاهش میده و حافظه کمتری مصرف میکنه.
Event Pooling: بازیافت رویدادها باعث میشه مصرف حافظه کمتر بشه، مخصوصاً تو اپهایی با تعداد زیادی رویداد.
هماهنگی با Virtual DOM:
Synthetic Events با سیستم Virtual DOM و Reconciliation در React هماهنگن. React میتونه رویدادها رو با تغییرات state و رندرینگ همگام کنه.
مدیریت سادهتر برای توسعهدهنده:
با Synthetic Events، نیازی نیست توسعهدهنده نگران تفاوتهای مرورگرها یا جزئیات اتصال رویدادها باشه. مثلاً تو React همیشه کار میکنه، بدون نیاز به مدیریت click یا touch به صورت جداگانه.
پشتیبانی از قابلیتهای پیشرفته:
Synthetic Events به React اجازه میدن قابلیتهایی مثل Concurrent Rendering (تو React 18) رو پیادهسازی کنه، چون میتونه اولویت رویدادها رو مدیریت کنه.
فرض کن میخوای یه دکمه بسازی که با کلیک روش، یه پیام لاگ کنه و رفتار پیشفرض (مثل ارسال فرم) رو متوقف کنه.
javascript
function FormButton() { const handleClick = (event) => { event.preventDefault(); // متوقف کردن رفتار پیشفرض console.log('کلیک شد:', event.target); }; return ( <form> <button ={handleClick}>کلیک کن</button> </form> ); }
توضیح:
onClick یه Synthetic Eventه که React مدیریتش میکنه.
event.preventDefault() تضمین میشه که تو همه مرورگرها به درستی کار میکنه.
React رویداد رو از ریشه اپلیکیشن میگیره و به کامپوننت مربوطه پاس میده.
javascript
const form = document.querySelector('form'); const button = document.querySelector('button'); button.addEventListener('click', (event) => { event.preventDefault(); // متوقف کردن رفتار پیشفرض console.log('کلیک شد:', event.target); });
توضیح:
اینجا باید خودت رویداد رو به عنصر DOM وصل کنی.
اگه مرورگر خاصی (مثلاً یه نسخه قدیمی) preventDefault رو متفاوت پیادهسازی کرده باشه، ممکنه مشکل پیش بیاد.
تفاوت در عمل:
تو React، نیازی نیست نگران پیدا کردن عنصر یا مدیریت تفاوتهای مرورگر باشی. Synthetic Event همهچیز رو ساده و یکپارچه میکنه.
تو Native Event، باید خودت همهچیز (از اتصال رویداد تا مدیریت سازگاری) رو مدیریت کنی.
هرچند React معمولاً با Synthetic Events کار میکنه، گاهی ممکنه نیاز به Native Events داشته باشی:
وقتی با کتابخانههای خارجی کار میکنی که مستقیماً با DOM کار میکنن (مثل jQuery یا Chart.js).
برای رویدادهایی که React پشتیبانی نمیکنه (مثل رویدادهای خاص مثل resize روی window).
وقتی نیاز به دسترسی مستقیم به DOM داری (مثلاً با ref).
مثال استفاده از Native Event در React:
javascript
import { useEffect, useRef } from 'react'; function WindowResize() { const handleResize = () => { console.log('اندازه پنجره تغییر کرد:', window.innerWidth); }; useEffect(() => { window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, []); return <div>تغییر اندازه پنجره رو چک کن</div>; }
توضیح:
اینجا چون resize یه رویداد windowه و React مستقیماً براش Synthetic Event نداره، از Native Event استفاده کردیم.
با useEffect مطمئن میشیم که listener موقع پاکسازی کامپوننت حذف میشه.
Native Events: رویدادهای خالص مرورگر که مستقیماً به DOM وصلن و ممکنه تو مرورگرهای مختلف رفتار متفاوتی داشته باشن.
Synthetic Events: wrapperهای React که رویدادهای Native رو استاندارد میکنن، با Virtual DOM هماهنگن، و رفتار یکپارچهای تو همه مرورگرها دارن.
چرا Synthetic Events؟
سازگاری بین مرورگرها.
بهینهسازی عملکرد با event delegation و pooling.
هماهنگی با Virtual DOM و سیستم رندرینگ React.
سادهسازی توسعه با API یکپارچه.
پشت صحنه: React رویدادها رو از ریشه اپلیکیشن مدیریت میکنه، SyntheticEvent میسازه، و با Virtual DOM و Reconciliation تغییرات رو اعمال میکنه.