انتخاب صندلی برای یک سینما در اهواز. تمام ایدهای که زیر هر فریمورک این صفحه هست، در پانزده سطر جاوااسکریپت ساده جا میشود، بدون نصب هیچ چیزی:
const Sandali = (id) => `[${id}${state.gerefte.includes(id) ? "x" : state.entekhab === id ? "*" : " "}]`function setState(next) { state = { ...state, ...next }; render(); }
اجرایش کنید و انتخاب A4 و بعد B3، ردیف را سه بار چاپ میکند، با نشانگری که جابهجا میشود و B4 که در تمام مدت گرفته میماند. دو جمله توضیح میدهند چه شد، و همان دو جمله کل موضوعاند.
کامپوننت تابعی است که وضعیت میگیرد و نشانهگذاری برمیگرداند. Sandali یکی از آنهاست، و صفحهای که چهار بار صدایش میزند هم؛ هیچکدام چیزی نگه نمیدارند و چیزی به یاد نمیآورند، و با همان وضعیت همان خروجی را میدهند. و setState وضعیت را جایگزین میکند و رندر را دوباره اجرا میکند، صفحه را ویرایش نمیکند. هیچجای آن برنامه صندلی A4 را پیدا نمیکند و کلاسش را عوض نمیکند؛ توصیف را دور میریزد و توصیف تازهای مینویسد.
معامله همین است. توصیف کردن کل صفحه از روی وضعیت فعلی خیلی راحتتر از حساب کردن این است که کدام چهار عنصر باید عوض شوند، و راحتتر است چون فقط یک توصیف هست بهجای یکی بهازای هر گذار ممکن. چیزی که فریمورک اضافه میکند همان بخشی است که آن پانزده سطر از رویش میپرد: فهرست صندلیها از نو حساب میشود و فقط تفاوت به DOM میرسد.
جایی که وضعیت زندگی میکند تنها تصمیم معماری است
هر چیزی که بالا گفته شد تا وقتی کار میکند که یک شی وضعیت هست. لحظهای که دو بخش صفحه به یک واقعیت نیاز داشته باشند از کار میافتد، و طراحی همانجا اتفاق میافتد. قاعده کوچک است و در هر فریمورک اینجا برقرار است: وضعیتی که دو کامپوننت لازم دارند به نزدیکترین والد مشترکشان بالا میرود. شبکه صندلیها و جمع قیمت هر دو به صندلی انتخابشده نیاز دارند، پس صندلی انتخابشده مال صفحهای است که هر دو را دارد، نه مال هیچکدامشان. پراپها پایین میروند و رویدادها بالا میآیند، و کل جریان داده همین است.
فهرستها یک چیز دیگر هم لازم دارند. کلید به فریمورک میگوید کدام عضو فهرست میان دو رندر کدام است، تا درج یک ردیف در بالا، ردیفها را جابهجا کند نه اینکه همهشان را از نو بنویسد. استفاده از موقعیت در آرایه بهعنوان کلید رایجترین راه اشتباه انجام دادن این کار است، چون موقعیت یک ردیف عوض میشود و هویتش نه. وقتی وضعیت از یک والد بزرگتر شد، پرسش میشود وضعیت مشترک وقتی برنامه بزرگ شد کجا زندگی میکند.
چهارتا، و تفاوتشان کمتر از چیزی است که بحثها نشان میدهند
هر چهارتا پاراگراف بالا را مسلم میگیرند. React و Vue یک زمان اجرا با خودشان میآورند، Svelte بهروزرسانیها را در زمان کامپایل حذف میکند، و Angular مسیریاب و فرمها و کلاینت HTTP را داخل جعبه میآورد بهجای اینکه انتخابشان را به شما بسپارد. پس راه صادقانه خواندن این انتخاب، دیدن این است که چه چیزی با آن میآید و چه کسی نزدیک شماست تا بپرسید. آن چهارتا کامپوننت، وضعیت و چرخه رندر، قالب، واکنشپذیری و ورودی ملایمتر، فریمورک کامل، با نظرهایش و یک کامپایلر بهجای یک زمان اجرا هستند.
چهار لایه
یک کامپوننت روی چه چیزی ایستاده است
هر لایه لایه بالای خودش را نگه داشته، و پایینیترین تنها لایهای است که مرورگر تا حالا اسمش را شنیده.
- کامپوننتهای شماتابعهایی از وضعیت. تنها لایهای که میداند صندلی چیست.مال شما
- فریمورکاجرایشان میکند، نتیجهها را مقایسه میکند، و تصمیم میگیرد چه عوض شدهReact، Vue، Svelte، Angular
- DOMدرختی که مرورگر واقعاً نگه میدارد، و تنها چیزی که میشود عوضش کردمال مرورگر
- HTML و CSSچیزی که آن درخت از آن ساخته شده، هرکس نوشته باشدشخود سکو
هیچ چیز شماره نخورده چون هیچکدام اول اتفاق نمیافتند. روی یک گوشی کند، وقت در دو لایه پایینی میگذرد، و هیچ انتخابی در لایه بالا این را عوض نمیکند.
ابزار، و سالی که این حرف درست است
Vite ابزار ساخت زیر بیشترشان است و رایگان و متنباز. جای webpack را برای پروژههای تازه گرفت، و تفاوتی که ساخت در انتظار بعد از ذخیره کردن یک فایل بود نه در خروجی نهایی. افزونه مرورگر خود فریمورک دومین چیزی است که باید نصب شود: درخت کامپوننت و وضعیت هر گره و علت آخرین رندر را نشان میدهد، و جای اضافه کردن یک print داخل تابع رندر را گرفت. TypeScript سومی است و اینجا بیشتر از تقریباً هر جای دیگری خودش را پس میدهد، چون قرارداد میان والد و فرزند دقیقاً همان پراپهاست.
و آنچه اینجا باید صریح گفته شود: هر سه ابزار بالا یعنی یک گام نصب. یک پروژه تازه با هرکدام از این فریمورکها صدها بسته از مخزن npm میگیرد، و همان گام است که از ایران میایستد. خود مخزن معمولاً جواب میدهد؛ چیزی که گیر میکند بستههایی است که موقع نصب یک فایل باینری از جای دیگری دانلود میکنند. جوابش یک بار تنظیم کردن نشانی آینه در پیکربندی npm است و بعد نگه داشتن پوشه بستهها؛ و اگر پروژهای دارید که باید روی ماشین کس دیگری هم ساخته شود، فایل قفل را کامیت کنید، چون بدون آن هر نصب تازه یک قمار دیگر است.
اشتباه: سراغ فریمورک رفتن پیش از آنکه وضعیت شکلی داشته باشد
گیر اینجا یاد گرفتن نحو نیست. این است که آدمها اینها را راهی برای ساختن یک صفحه میبینند، و اینها آن نیستند؛ راهی هستند برای همخوان نگه داشتن یک صفحه با یک وضعیت. صفحهای که هیچ وضعیت متغیری ندارد از هیچکدامشان چیزی نمیگیرد و بابتش یک گام ساخت و یک زمان اجرا و یک پوشه وابستگی میپردازد.
صفحه رزرو آن سینما مورد منصفانهای است، چون ظاهر یک صندلی واقعاً به دو واقعیت بستگی دارد که وقتی کسی نگاه میکند عوض میشوند. صفحه ساعت کار سینما نیست، و رندر کردنش از داخل یک درخت کامپوننت هیچ چیزی نمیخرد. نشانهای که فریمورک برای کار اشتباه به کار رفته: شی وضعیت خالی است یا یک فیلد دارد، و هر کامپوننت از جای دیگری میخواند.
چیزی که هیچکدام از اینها پوشش نمیدهد این است که صفحه باید پیش از اجرای هرکدام از اینها برسد، که بکاند است، و اینکه کامپوننتها هنوز دارند HTML مینویسند هر شکلی که نحوشان باشد. زبانی هم که هر چهارتا با آن نوشته شدهاند جاوااسکریپت است، و همه اینها زیر وب نشستهاند.