برنامه نویسی

معرفی Oats~i – چارچوب وب باز

Summarize this content to 400 words in Persian Lang
من حدود پنج سال است که یک توسعه دهنده وب فعال هستم. در اواخر سال 2019، زمانی که من به طور رسمی توسعه وب را شروع کردم، توسط اکوسیستم وسیعی از ابزارهای توسعه وب احاطه شده بودم که می توانستم از آنها برای ایجاد وب سایت برای مشتریان و هر پروژه شخصی که داشتم استفاده کنم.

اما متوجه شدم که مسیر خودت را انجام بده. نه به این دلیل که به لحظات دردناک و دردناک عادت کرده‌ام، بلکه به این دلیل که می‌خواستم توسعه وب را از اصول آن یاد بگیرم، نه اینکه مستقیماً وارد چارچوبی شوم و دانش خود را از آنجا بسازم.

علاوه بر این، این چیزی است که اکثر توسعه دهندگان وب با تجربه توصیه می کنند. HTML، CSS، و جاوا اسکریپت وانیلی را بیاموزید، و هر چیز دیگری که در کنار آن باشد، در پارک بسیار جذاب خواهد بود.

خوب، اینجا هستیم، پنج سال بعد و به نوعی، من یک چارچوب وب برای خودم ساختم. چیزی که به عنوان یک تمرین یادگیری ساده در مورد نحوه کار APIهای وب و وب شروع شد، در نهایت به یک پروژه تمام عیار با لحظات بی‌شماری سر خاراندن، ناامیدی و اورکا تبدیل شد.

معرفی Oats~i، چارچوب وب باز که همچنین شما را به اصول اولیه بازمی گرداند. Oats~i ساختاری را ارائه می دهد که به شما امکان می دهد برنامه های وب را با استفاده از HTML، CSS، و جاوا اسکریپت Vanilla ایجاد کنید، با قابلیت توسعه قدرتمند، رندر سمت سرور، مسیریابی مبتنی بر رضایت، واکنش پذیری از طریق مدیر داده، مدیر نمایش، و قلاب ها، یک قطعه سیستم مشاهده مبتنی بر، مشاهده پنل‌ها برای پشتیبانی از طرح‌بندی‌های اضافی، پنجره‌های بازشو، و نمایش‌های سفارشی در بالای قطعات، پشتیبانی از ویژگی‌های مرور وب «بومی» مانند پارامترها، پرس و جوها، و اهداف، صفحه‌بندی، تقسیم کد و بارگذاری تنبل برای جاوا اسکریپت و مشاهده بسته‌ها

همه اینها به صورت بومی با فریمورک ارائه می‌شوند و در بالای Webpack به عنوان بسته‌کننده ماژول ترجیحی اجرا می‌شوند.

Oats~i به محیط سرور شما اهمیتی نمی دهد زیرا یک سیستم کاملاً مبتنی بر مشتری است. هیچ JS در حال اجرا روی سرور وجود ندارد، بنابراین برای استقرار یک برنامه Oats~i نیازی به راه اندازی سرور خاصی نیست.

اما قبل از اینکه به جزئیات بپردازیم، اکنون کجا اجرا می شود؟

اینجا: https://www.vertesolutions.com

آن سایت یک سایت تولیدی برای مشتری است که در زمینه مشاوره زیست محیطی و تجارت زیست محیطی فعالیت می کند. این کسب و کار Verte Environmental Solutions نامیده می شود، بنابراین اگر متوجه شدید که من به «وب سایت Verte» اشاره می کنم، این همان سایتی است که به آن اشاره می کنم.

Oats~i در حال حاضر در هیچ جای دیگری اجرا نمی شود.

ویرایش: کد منبع نیز عمومی است. https://github.com/Oats-i/Oats-i

قبل از رسیدن به این نقطه، من در طول سال ها در حال توسعه چارچوب در پنل مدیریت سایت (که سفارشی ساخته شده است)، آزمایش، به روز رسانی و افزودن ویژگی های جدید بوده ام. بنابراین، اگر برخی از مواردی که در اینجا در سایت مشتری در مورد آنها صحبت خواهم کرد را از دست دادید، مطمئن شوید که آنها روی ادمین اجرا می شوند.

همچنین، چیزی که من معرفی می‌کنم یک چارچوب نسبتاً کامل است، با چند ویژگی برای صحبت در مورد. بنابراین هشدار دهید، این یک قطعه طولانی خواهد بود. و من سعی کردم تا آنجا که می توانم آن را ویرایش کنم تا کوتاهتر شود. با این حال، من با این مقدمه به اصل همه چیز دست زدم. بقیه قسمت قبل از اینکه در پست‌های بعدی عمیق‌تر شویم، یک خراش از سطح است.

پس این مقدمه بس است.

بیایید کمی عمیق‌تر به Oats~i بپردازیم، همانطور که تا به حال آن را ساخته‌ام، و به برخی از مواردی که در خارج از جعبه ارائه می‌دهد و برنامه‌ریزی‌هایی که برای حرکت رو به جلو دارد، نگاه کنیم.

یک چارچوب وب باز

با نامیدن Oats~i یک چارچوب وب باز، منظورم این است که Oats~i یک چارچوب ساده و در عین حال قابل توسعه است که کد آن را می توان با HTML ساده و جاوا اسکریپت Vanilla نوشت، البته CSS ابزار یک ظاهر طراحی واقعی است. از این راه‌اندازی ساده، می‌توانید موتورهای قالب، کتابخانه‌های css و ابزارهای دیگر، شخص ثالث یا سفارشی خود را اضافه کنید، تا زمانی که Webpack به آن اجازه دهد و بتوانید آن را پیکربندی کنید.

سیستم مبتنی بر قطعه

Oats~i از طریق یک سیستم ساخت کار می کند که قطعات را به عنوان “کامپوننت” یا قطعات اصلی برنامه وب ایجاد می کند. به عنوان مثال این نماهای ساده را در نظر بگیرید:

هر دو تصویر دارای “نمای ریشه” برنامه هستند که نمای اصلی برنامه است که کاربر همیشه خواهد دید. سپس نماهای دیگر (قطعات) به صورت پویا در داخل ارائه می شوند.

نمای ریشه می‌تواند شامل پیوندها یا دکمه‌های پیمایش اصلی و سایر نماهایی باشد که کاربر همیشه در برنامه مشاهده می‌کند و معمولاً تغییر نمی‌کند.

بقیه نماهای داخل نمای ریشه تغییر خواهند کرد، و این بر اساس بارگیری و بارگیری قطعات از برنامه، بر اساس مسیریابی کاربر است. فرگمنت ها از طریق یک فرآیند ساخت گذر می کنند که در درجه اول نمای مورد نظر را دریافت می کند، آن را در گره والد هدف قرار می دهد و سپس به شما امکان می دهد بقیه برنامه و منطق تجاری خود را سیم کشی کنید.

یک فرآیند ساخت Oats~i معمولاً متدهای اصلی زیر را در قطعه شما فعال می کند:

//gets the view for your fragment
async initializeView(cb){
}

//triggers after the fragment view has been attached to the DOM
onUIBind(serverSideRendered){
}

//triggers after the fragment has completed building and anytime its rebuilt for the same route
async onQueryParamsDataUpdate(changedParams, data, savedState, routeParams, isServerSide){
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و اساساً همین است.

با چنین ساختار اسکلتی شما چند انعطاف دارید، مانند:

ارائه HTML ساده یا بارگیری نماهای پیچیده با استفاده از موتورهای قالب (به انتخاب شما)

اولین روشی که باطل می کنید (initializeView()) را می توان به صورت زیر تکمیل کرد:

async initializeView(cb){

const viewAsString = `My view`;
this.onViewInitSuccess(viewAsString, cb);
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نمای خود را به عنوان یک رشته HTML دریافت می کنیم و آن را به متد داخلی (onViewInitSuccess()) ارسال می کنیم که همچنین callback ارسال شده به متد اصلی را نیز می گیرد.

فراخوانی ()onViewInitSuccess فرآیند ساخت را برای ادامه مراحل بعدی آغاز می کند.

نوشتن HTML به‌عنوان یک رشته در JS ساده است و Oats~i اجازه می‌دهد، اما اغلب ممکن است مشکل ساز شود. با این حال، به جای ساختن یک نحو یا سیستم جدید برای نوشتن نماها برای Oats~i، Oats~i به شما این امکان را می‌دهد تا هر موتور قالبی را که برای مورد استفاده شما بهتر کار می‌کند، وصل کنید، آن را در پیکربندی بسته وب خود سیم‌کشی کنید و اجازه دهید جادویی خود را انجام دهد. .

در مورد Verte، من از handlebars ترکیب شده با handlebars-loader برای نوشتن فایل‌های view جداگانه با فرمت hbs استفاده می‌کنم و به سادگی آن‌ها را در کد خود مورد نیاز می‌دانم.

بنابراین، به جای

const viewAsString = `My view`;

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

دیدگاه های من اکنون به صورت زیر ارائه می شود:

const viewAsString = require(“./relative/path/to/view.hbs”)(myTemplatingData);

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

به عنوان مثال، اگر بخواهم به جای آن از ejs استفاده کنم، فقط باید پیکربندی بسته وب خود را به روز کنم و از دستور واردات مناسب برای آن مورد استفاده کنم.

Oats~i فقط اهمیت می دهد که نمای ارسال شده به آن یک رشته HTML باشد.

نماهای منبع یابی شبکه

Oats~i تا جایی پیش می رود که به شما امکان می دهد بازدیدهای خود را از طریق شبکه منبع کنید. تا حدی به همین دلیل است که async در متد ()initializeView وجود دارد.

Oats~i همچنین از شما انتظار دارد که احتمالاً در این مرحله تماس های شبکه ای برقرار کنید، یا برای یک نمای کامل بر اساس نوع کاربر یا سایر عوامل، یا داده های قالب را بر اساس دیدگاه و منطق تجاری خود دریافت کنید.

کاری که در اینجا انجام می دهید کاملاً به دلایل تجاری و فنی شما بستگی دارد.

**نکته: **دلیل خوبی وجود دارد که چرا سیستم ساخت منتظر وعده‌ها در مرحله ساخت برای حل با استفاده از await یا then() نمی‌ماند، بلکه در عوض از یک callback ارسال شده به متدهای مربوطه استفاده می‌کند. این زمانی مشخص خواهد شد که در قسمت بعدی به بررسی نحوه عملکرد Oats~i بپردازیم.

Vanilla JavaScript یا یک کتابخانه JS سازگار برای برنامه یا منطق تجاری

کد Oats~i در جاوا اسکریپت وانیلی است که مرورگرهای وب زبان “بومی” آن را درک می کنند. با این حال، چند انعطاف وجود دارد که می توانید هنگام نوشتن منطق کسب و کار خود داشته باشید.

به عنوان مثال، به هر دلیلی می توانید jQuery را در پروژه خود پورت کنید و از آن برای نوشتن بخشی از منطق خود استفاده کنید. من در واقع این کار را مدتها قبل انجام دادم، حتی قبل از اینکه Oats~i به وضعیت فعلی خود ساخته شود، تا حدود پنج خط کد برای افکت های اسکرول صاف در وب سایت Verte بنویسم. (TLDR، من تنبل بودم که فراتر از Stack Overflow فکر کنم، lol).

از نظر تئوری می‌توانید از Oats~i در محیط TypeScript استفاده کنید، اما هنوز این مورد را آزمایش نکرده‌ام. تنها استفاده ای که از تایپ اسکریپت داشتم، سیستم تایپ آن، همراه با JSDocs، برای مستندسازی انواع در چارچوب بود، روشی که مدتی قبل مستندسازی کردم.

می‌توانید در مورد ادغام JSDocs و TypeScript برای اهداف تایپ، بدون فرآیند ساخت، اینجا بخوانید.

تقسیم کد و بارگذاری تنبل

Webpack یک ابزار توسعه وب قدرتمند است که امکان پیکربندی پروژه های بسیار پیچیده را فراهم می کند و به تیم های توسعه انعطاف پذیری لازم را برای ساخت یک پروژه با مشخصات منحصر به فرد آن می دهد.

Oats~i در بالای Webpack اجرا می‌شود، با چارچوبی که اساساً به ویژگی تقسیم کد و بارگذاری تنبل Webpack برای پشتیبانی از تکه‌ها و بسته‌های قطعه ناهمگام متکی است.

این بدان معنی است که قطعات شما می توانند در یک بسته بارگذاری شوند یا با استفاده از بسته وب به چند تکه تقسیم شوند و سرعت بارگذاری اولیه برای برنامه وب Oats~i شما بهینه شود. اگر برنامه شما به آن‌ها نیاز دارد، این را با نماهای منبع شبکه مرتبط کنید، و راه‌های متعددی وجود دارد که می‌توانید برنامه خود را در Oats~i بهینه کنید تا از بهترین تجربه کاربر در مورد زمان بارگذاری اطمینان حاصل کنید.

تنظیمات پیشرفته پروژه با استفاده از Webpack

شاید بزرگترین مزیت داشتن وب پک به عنوان پایه Oats~i پیکربندی بزرگی است که در اختیار شما گذاشته شده است که به شما امکان می دهد برنامه خود را همانطور که به آن نیاز دارید بسازید.

به همین دلیل است که می‌توانید موتورهای قالبی را تنظیم کنید که مطابق با فرآیند رندر نمایش شما باشد، babel و سایر لودرها/افزونه‌ها را برای برنامه خود پیکربندی کنید، و به سادگی چیزی بسازید که کاملاً با مشخصات پروژه شما مطابقت داشته باشد.

Oats~i یک پیکربندی پایه وب بسته ساده را اجرا می کند که برای ایجاد نماها یا قالب های سمت سرور شما، handlebars-loader، html-loader، css loader، asset loader و HTMLWebpackPlugin را راه اندازی می کند. با استفاده از webpack-merge، می توانید این پیکربندی ها را گسترش دهید و برنامه وب خود را همانطور که می خواهید معماری کنید.

این باعث می شود Oats~i بسیار شبیه یک سیستم plug-and-play عمل کند. این یک اسکلت به شما می دهد و می توانید برنامه خود را به دلخواه دور آن بپیچید و پیکربندی کنید.

مسیریابی

مسیریابی یک ویژگی پیش فرض در Oats~i است. در واقع، برای اجرای برنامه، باید اطلاعات مسیریابی را ارائه دهید که برنامه از آن برای مقداردهی اولیه خود و مدیریت ناوبری کاربر و رندر قطعه استفاده می کند.

اطلاعات مسیریابی ساده به این صورت است:

Const MyRoutingInfos = [
{
route: “/my-route”,
target: myMainFragmentBuilder,
nestedChildFragments: [
myNestedChildFragmentBuilder
] }
]

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

هنگامی که Oats~i از سرور بارگیری می‌شود، آدرس اینترنتی فعلی را بررسی می‌کند و در اطلاعات مسیریابی ارائه شده مطابقت با آن پیدا می‌کند. در مورد Verte، وقتی «https://dev.to/» را بارگیری می‌کنید، Oats~i اطلاعات مسیریابی را با آن مسیر به‌عنوان همسان جستجو می‌کند و سپس قطعات را به ترتیب از «هدف» به هر قطعه فرزند تودرتو باد می‌کند.

همچنین می‌توانید یک مسیر پیش‌فرض ارائه کنید که Oats~i سعی می‌کند برنامه را از آن راه‌اندازی کند، مگر اینکه مشتری صفحه را از مسیر معتبری که در اطلاعات مسیریابی شما آمده است، تهیه کرده باشد.

پارامترها در مسیریابی

Oats~i همچنین از استفاده از پارامترها در مسیرها، با استفاده از نحو کولون که معمولاً در express استفاده می‌شود، پشتیبانی می‌کند.

بنابراین، مسیری که مانند /:myParams تعریف شده است معتبر است و برای مسیرهایی مانند /user-1، /user-2، /user-3 نقشه‌برداری می‌کند.

Oats~i یک قدم جلوتر می رود و این پارامترها را برای شما تجزیه می کند.هنگام تنظیم قطعه خود، گزینه تنظیم پارامترهایی را دارید که باید مراقب آنها باشد. نام پارامتر باید دقیقاً با نام استفاده شده در اطلاعات مسیریابی شما مطابقت داشته باشد.

هنگام ساخت قطعه، Oats~i مقدار را تجزیه می کند، هر گونه تغییر را یادداشت می کند و دو آرگومان را به متد ()onQueryParamsDataUpdate شما ارسال می کند. اینها موضوعی از همه پارامترهای تماشا شده هستند که تغییر کرده اند، و مقدار فعلی همه پارامترهای تماشا شده.

بنابراین، اگر قطعه ای دارید که اطلاعات کاربر را نشان می دهد، که در مسیر /:userID تعریف شده است، و مشتری ابتدا به /user-xyz هدایت می شود، می توانید مقدار userID را به عنوان user-xyz بخوانید. اگر کلاینت دوباره مسیر یابی کند و این بار مسیر /user-abc باشد، بلافاصله متوجه خواهید شد که مقدار userID به user-abc تغییر کرده است و می توانید به طور مناسب پاسخ دهید.

پشتیبانی پرس و جو

پرس و جوها همچنین بخش اصلی وبگردی و آدرس های اینترنتی هستند. Oats~i همچنین پرس‌و‌جوها را برای شما تجزیه می‌کند، به شرطی که به قطعه بگویید آنها را با استفاده از کلیدهایشان تماشا کند.

به عنوان مثال، اگر مسیر /:userID شما به /user-3?promptUpgrade=true نگاشت شود، و در قطعه خود مشخص کنید که می خواهید به روز رسانی های درخواست را با کلید “promptUpgrade” مشاهده کنید، آنها تجزیه و به قسمت ارسال می شوند. روش onQueryParamsDataUpdate() نیز هست.

با این حال:

شما نمی توانید با استفاده از پرس و جو، مسیرها را در اطلاعات مسیریابی خود بنویسید. فقط پارامترها پشتیبانی می شوند. Oats~i به دنبال اطلاعات مسیریابی معتبر برای یک url معین پس از کوتاه کردن هرگونه پرسش و هدف می‌گردد. تجزیه و تحلیل پس از آن انجام می شود.

وب‌سایت Verte در حال حاضر از این مکانیسم هنگام نمایش نماها برای مقالات وبلاگ در صفحه مقاله وبلاگ استفاده می‌کند. مسیر برای هر مقاله پارامتری است و ما فقط به تغییر در پارامتر تماشا شده پاسخ می دهیم.

مسیریابی مبتنی بر رضایت

این شاید یک ویژگی بسیار منحصر به فرد از Oats~i باشد. مسیریابی مبتنی بر رضایت به شما قدرت تجربه کاربر را می‌دهد و به شما این امکان را می‌دهد که در صورت وجود هر گونه فرآیند معلقی که همه در برنامه کنترل می‌شوند، به کاربران در مورد دور شدن از یک صفحه مهم هشدار دهید.

Oats~i به جای استفاده از API استاندارد مرورگر ارائه شده که یک کادر محاوره ای را باز می کند، از ترکیبی از History API و مدیریت حالت برای تشخیص پاپ یا پیمایش استفاده می کند، از قطعات رندر شده فعلی درخواست رضایت می کند، تلاش های پیمایش بعدی را متوقف می کند و فقط ادامه می دهد. اگر کاربر به آن اجازه دهد.

اگر کاربر انتخاب کند که در نمای فعلی خود باقی بماند، Oats~i مسیر ناوبری مرورگر را به حالت اولیه بازیابی می کند.

البته، اینکه کاربران هر بار که می خواهند در برنامه شما حرکت کنند، روی “ok” کلیک کنند، ایده بدی است. بنابراین، به‌طور پیش‌فرض، قطعات Oats~i و پانل‌های مشاهده (در ادامه در مورد آنها بیشتر توضیح خواهیم داد) به طور پیش‌فرض با تلاش ناوبری موافقت می‌کنند.

Verte به صورت داخلی از این برای محافظت از سرپرست هنگام مدیریت محتوای وبلاگ استفاده می کند، در صورتی که پیش نویس فعلی هنوز توسط اسکریپت ذخیره خودکار در دلتای زمانی خود انتخاب نشده باشد. در صورتی که سرپرست بخواهد از ویرایشگر وبلاگ دور شود و پیش‌نویس‌های ذخیره‌نشده وجود داشته باشد، از طریق یک گفتگو اخطاری دریافت می‌کنند و انتخاب می‌کنند که به پیمایش دور ادامه دهند یا در صفحه بمانند و کار خود را به صورت دستی ذخیره کنند.

پنجره‌های بازشو، دیالوگ‌ها و طرح‌بندی‌های بیشتر با استفاده از پنل‌های نمایش

در Oats~i، چارچوب در درجه اول یک مسیر را از طریق قطعات ارائه می کند. با این حال، یک ابزار اضافی به نام view panels وجود دارد که به شما امکان می دهد نماهای دیگری را که ممکن است قطعه شما ممکن است به آن نیاز داشته باشد ارائه دهید. اینها شامل کادرهای گفتگو، پانل های همبرگر یا حتی بارگذاری صفحه نمایش با اطلاعات سفارشی است که ممکن است کاربر به آن نیاز داشته باشد.

برای ایجاد یک پنل نمایش، باید آن را از طریق مدیر پنل های نمایش درخواست کنید. Oats~i خود نماها را برای قطعات و پانل‌های مشاهده مدیریت می‌کند، به این معنی که شما هرگز مجبور نیستید منطق بنویسید تا نماهای قطعه اصلی خود را به DOM متصل کنید یا زمانی که پانل view یا قطعه مرتبط با آن به دلیل تغییر در ناوبری از بین رفت، آنها را حذف کنید.

یک پنل نمایش که توسط مدیر پنل‌های مشاهده ایجاد می‌شود نیز به‌طور خودکار به فرآیند مسیریابی رضایت قطعه متصل می‌شود و به شما امکان می‌دهد عملکرد قطعه را گسترش دهید.

نمایش پانل ها همچنین می توانند پارامترها و پرس و جوها را تماشا کنند.

پانل‌های مشاهده مسیر راه‌اندازی و مستقیم

پانل‌های مشاهده را می‌توان با تغییر مسیر یا مستقیماً از طریق تماس با مدیر پنل‌های نمای قطعه فعال کرد. برای اولی، این جایی است که داشتن پرس و جو در مسیر شما و پیوند آنها به یک پنل مشاهده در قطعه می تواند مفید باشد.

اگر مسیری دارید “/:post-id” که در حال حاضر در مرورگر به صورت “/nice-post?showComments=true” نمایش داده می شود، می توانید از پانل مشاهده مسیر راه اندازی شده در قطعه استفاده کنید تا به طور خودکار یک پانل جانبی ظاهر شود. نظرات پست را بارگذاری می کند و به کاربر اجازه می دهد آنها را بخواند.

این ویژگی معمولاً از طریق متد ()onQueryParamsDataUpdate قابل دسترسی است. فراخوانی super (در صورتی که آن را لغو کرده باشید) مدیر پانل‌های نمای قطعه را فراخوانی می‌کند تا هر پانل نمای راه‌اندازی مسیر را ارائه کند.

بزرگترین مزیت این نوع تنظیم این است که رندر و رفتار پنل نمای شما اکنون به ناوبری گره خورده است و تجربه کاربر را طبیعی تر می کند.

بنابراین، با توجه به مثال ما، اگر کاربر به “/nice-post?showComments=true” پیمایش کند، نظرات را بخواند و به عقب فشار دهد، مسیر به “/nice-post” تغییر خواهد کرد، مدیر پنل های نمایش این را یادداشت می کند. تغییر دهید، و تا زمانی که رضایت داده شده باشد، به طور خودکار فرآیند تخریب پانل نمایش را آغاز می کند.

درست مانند قطعات، پنل‌های مشاهده نیز به‌طور پیش‌فرض رضایت می‌دهند. بنابراین، فقط در صورت لزوم باید روش رضایت را لغو کنید.

واکنش پذیری و مدیریت داده ها

یک چارچوب وب مدرن بدون لمس خوبی از واکنش پذیری و مدیریت داده کامل نمی شود. و اینجاست که شاید مهم‌ترین تفاوت بین Oats~i و سایر چارچوب‌های وب ظاهر می‌شود.

Oats~i به طور خودکار نماها را به یک داده یا حالت جفت نمی کند.

در عوض، این به طور کامل به توسعه دهنده واگذار می شود تا آن را بر اساس برنامه یا منطق تجاری خود انجام دهد.

همانطور که هست، می‌توانید از Oats~i برای ساختن یک برنامه وب با چندین صفحه استاتیک که در زیر قطعات رندر شده‌اند و پانل‌ها را مشاهده کنید، استفاده کنید و آن را در آن پایان دهید. برنامه فقط کار خواهد کرد. اگر می‌خواهید داده‌ها، تماس‌های شبکه و واکنش‌پذیری را اضافه کنید، ابزار مدیریت داده همه چیز را پوشش می‌دهد، و تنها تا محدوده‌ای که شما تعیین می‌کنید، بدون تأثیر بر روی نماها یا داده‌های اطراف.

بیایید به مدیر داده و ابزارهای پشتیبانی آن نگاه کنیم: رابط شبکه و مدیران مشاهده.

مدیر داده ها

مدیر داده یک ابزار Oats~i است که به شما امکان می دهد داده ها، منابع سرور و نماهای کلاینت را با هم گره بزنید. مدیر داده مجموعه‌ای از مدل‌ها را نگه می‌دارد، یک مدل قطعه اصلی یا نوع داده مرتبط با بخشی از برنامه شما و نماهای انتخابی آن است.

در حال حاضر، من آن را طوری طراحی کرده‌ام که یک مدل را به‌عنوان یک شی با آرایه‌های تو در تو در نظر بگیرم، زیرا رایج‌ترین فرمت برای انتقال داده‌ها به منابع مشتری و سرور (به عنوان Json) است.

بنابراین، یک مدل ساده می تواند چیزی شبیه به این باشد:

{
my: string,
simple: number,
obj: {
ofArrays: number[],
objArrays: { objKey: string }[] }
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

مدیر داده با تعیین محدوده مدل خود کار می کند. این بدان معنی است که هر بیت از مدل را می توان به عنوان یک واحد در نظر گرفت و مجموعه ای از کلیدهای جدا شده از نقطه را ایجاد می کند که مقدار یا نوع خاصی را در داده های شما تعریف می کند.

به عنوان مثال، در مثال بالا، مدیر داده مدل را به حوزه های زیر تقسیم می کند: “MODEL_ROOT | my | ساده | obj | obj.ofArrays | obj.objArrays | obj.objArrays.array.objKey ”

این دامنه ها نشان دهنده:

MODEL_ROOT -> {
my: string,
simple: number,
obj: {
ofArrays: number[],
objArrays: { objKey: string }[] }
}

my -> string,

simple -> number

obj -> {
ofArrays: number[],
objArrays: { objKey: string }[] }

obj.ofArrays -> number[]

obj.objArrays -> { objKey: string }[]

obj.objArrays.array.objKey -> string

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

می‌توانید این محدوده‌ها را به‌عنوان مسیرهای جداشده نقطه‌ای برای یک قطعه داده مجزا در نظر بگیرید.

با استفاده از این حوزه‌ها، مدیر داده‌ها سپس به شما، توسعه‌دهنده، کنترل دقیق داده‌های شما را می‌دهد که به هر یک از این داده‌ها اجازه اختصاص یک رابط شبکه یا مشاهده مدیر(ها) می‌دهد.

بیایید به طور سطحی به بررسی این دو بپردازیم.

رابط شبکه

در اکثر برنامه‌ها (بومی یا وب)، داده‌هایی که به کاربر نشان داده می‌شوند از یک منبع خارجی، یک سرور، منبع می‌شوند. بنابراین، مدل داخلی اغلب به یک رابط API نیاز دارد که بین خود و منبع خارجی قرار گیرد.

در مورد Oats~i، رابط شبکه عملیات CRUD مورد نیاز شما را در رابطه با داده های نگهداری شده توسط مدیر داده انجام می دهد و اطمینان حاصل می کند که هر دو طرف همگام هستند.

رابط شبکه به عنوان یک شی با سه روش تعریف می شود:

getReqBody()

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این متد بدنه درخواست و سایر داده ها مانند متد، آدرس، هدر و غیره را دریافت می کند.

onDataLoadPostProcess()

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

از آنجایی که نوع داده‌های پاسخ و نوع مدل داخلی شما ممکن است متفاوت باشد، رابط شبکه به شما امکان می‌دهد پاسخ را پس‌پردازش کنید و داده‌های نهایی را در نوع مدل مدیر داده ارائه کنید.

onDataLoadError()

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این روش به شما امکان می دهد در صورت عدم موفقیت تماس شبکه، پاسخ خطا را فرمت کنید.

محدوده رابط شبکه

طراحی های API متنوع هستند، به این معنی که آدرس ها یا مسیرهای مورد استفاده برای انجام عملیات CRUD برای یک قطعه داده معین می تواند متفاوت باشد.

به عنوان مثال، یک برنامه رسانه اجتماعی می تواند یک API متفاوت برای بارگیری همه پست ها داشته باشد و هر پست دارای API های منحصر به فردی برای ارسال مجدد، لایک یا گزارش پست باشد.

با فرض چنین معماری، استفاده از محدوده در مدیریت داده به شما اجازه می دهد تا رابط های شبکه منحصر به فردی را برای هر محدوده مشخص کنید.

به عنوان مثال، می‌توانید یک رابط شبکه برای تماس شبکه MODEL_ROOT (که پست‌ها را بارگیری می‌کند)، تماس شبکه “repost” و هر تماس دیگری که می‌تواند خارج از ساختار مدلی که مدیر داده نگه می‌دارد، داشته باشید.

این به شما یک روش منحصربفرد برای مشاهده داده‌هایتان می‌دهد، آن‌ها را از یک منبع بزرگ با یک نقطه پایان مشترک به مجموعه‌ای از چندین واحد داده که می‌توان به طور مستقل از طریق مدیر داده مدیریت کرد، تجزیه کرد.

نکته کلیدی که در اینجا باید به آن توجه داشت این است که شما فقط می توانید یک رابط شبکه در هر محدوده داشته باشید، و یک “نقطه پایانی” واحد برای هر قطعه داده با محدوده در مدل خود ایجاد کنید.

مشاهده مدیر

از طریق رابط شبکه، مدیر داده اکنون می تواند داده ها را بین مدل خود و سرور همگام نگه دارد. حالا در مورد نمایش آن به کاربر و مهمتر از آن نشان دادن زمانی که در حال تغییر است، چطور؟

اینجاست که view manager وارد می شود.

مشاهده مدیران به جهش‌ها یا تغییراتی که در داده‌های نگهداری شده توسط مدیر داده اتفاق می‌افتد، از طریق عملیات شبکه یا تغییر مستقیم درون برنامه پاسخ می‌دهند.

Oats~i در حال حاضر از دو نوع view manager پشتیبانی می کند – یک مدیر نمای استاندارد و یک مدیر نمای لیست.

یک مدیر نمای استاندارد برای نماهای ساده با مؤلفه هایی که روی یک لیست کپی نشده اند ایده آل است. از سوی دیگر، یک مدیر نمای لیست برای نماهای “پیچیده” با اجزای view کپی شده روی یک لیست بهترین است.

صرف نظر از نوع، یک مدیر view تغییرات زیر را در یک مدل یا انواع محدوده آن به شما می گوید:

onMutate()

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این روش زمانی فعال می شود که یک نوع داده از محدوده در حال تغییر است

onCommit()

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این روش زمانی فعال می شود که یک جهش در نوع داده محدوده تکمیل شده باشد، بنابراین انجام می شود

onCancel()

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این روش زمانی فعال می شود که جهشی از نوع داده محدوده لغو شده باشد

onError()

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این روش زمانی فعال می شود که یک جهش از نوع داده محدوده با خطا مواجه شده باشد و به شما امکان می دهد دوباره امتحان کنید.

همچنین مجموعه‌ای از متدهای سازنده وجود دارد که به شما امکان می‌دهد یک نما (به عنوان یک رشته HTML) پر از داده‌های خود را منتقل کنید. این روش ها همچنین بسته به جهش، به شما اطلاع می دهند که چه زمانی نما متصل شده یا در شرف جدا شدن است.

این سه روش عبارتند از:

inflateRoot()

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نمای قالب را به عنوان رشته ای برای داده های ارائه شده دریافت می کند

onViewAttach()

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

زمانی تماس می گیرد که نما به DOM متصل شده باشد

onViewDetach()

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

زمانی که نمای در شرف جدا شدن از DOM است تماس می گیردنتایج این تعاملات را می توانید در صفحات وبلاگ وب سایت Verte مشاهده کنید.

با استفاده از ترکیبی از روش‌های سازنده، قلاب‌های ریشه، و قلاب‌های مؤلفه، نماهای پویا مبتنی بر داده از بخش‌های مقاله وبلاگ و وبلاگ می‌توانند انیمیشن‌های بارگیری را هنگامی که داده‌ها را از شبکه منبع‌یابی می‌کنیم نشان دهند، پیام‌های خطا را در صورت خرابی نشان دهند. و پس از تکمیل داده های جدید از رابط شبکه، نماها را پر کنید.

یک مدیر نمایش همچنین دارای قلاب‌های مؤلفه‌ای خواهد بود که امکان واکنش‌پذیری دانه‌بندی‌شده حتی با عناصر هر گره مشاهده را فراهم می‌کند.

به عنوان مثال، با استفاده از مدل:

{
my: string,
simple: number,
obj: {
ofArrays: number[],
objArrays: { objKey: string }[] }
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و یک مدیر نمای دامنه “MODEL_ROOT” (بنابراین کل مدل)، می توانیم فرض کنیم که مولفه نمای اصلی که داده های محدوده MODEL_ROOT را نشان می دهد، دارای اجزایی در داخل خود است که من داده های خاص موجود در “my” را نشان می دهد، ” ساده، «obj»، یا به طور کلی دامنه های فرزند MODEL_ROOT.

بنابراین، می توانید یک جزء یا عنصر از دیدگاه خود را تنظیم کنید تا به تغییرات این مقادیر “کودکی” واکنش نشان دهد.

همه این روش‌های hook یک پارامتر viewNode دریافت می‌کنند که توسط view manager به آنها ارسال می‌شود، بنابراین شما همیشه مرجعی دارید که این تغییرات داده‌ها با کدام گره view مرتبط است و اجزای آن را در صورت نیاز جستجو کنید.

با این حال، زمانی که دیگر نیازی به این عناصر نمای اصلی نیستند، نباید خود را به خود زحمت دهید. مدیر view این کار را برای شما انجام می دهد.

بدون DOM مجازی

Oats~i از طریق DOM مجازی عمل نمی کند. درعوض، قطعات، پنل‌های مشاهده، و مدیران مشاهده مستقیماً از APIهای DOM برای درج یا حذف عناصر DOM استفاده می‌کنند.

پس از درج کامپوننت view خود در DOM، مدیر view مرجع مستقیم آن را در قلاب های سازنده، ریشه و کامپوننت در اختیار شما قرار می دهد. بنابراین، می‌توانید مستقیماً شنونده‌ها را اضافه کنید، ویژگی‌ها را تغییر دهید یا به سادگی عنصر DOM را با استفاده از apis DOM مستقیم دستکاری کنید.

مدیریت چرخه حیات

بخش اصلی یک برنامه وب پیچیده مدیریت چرخه حیات است. Oats~i فرآیند مدیریت چرخه حیات خود را برای قطعات و پنل‌های مشاهده دارد، که عملکردهای آن به ابزارهای دیگر مانند مدیر داده، مدیران مشاهده و درخواست از راه دور گسترش می‌یابد (ابزار واقعی که مدیر داده در ارتباط با رابط شبکه از آن استفاده می‌کند. برقراری تماس های شبکه).

بنابراین، مستقیماً با استفاده از Oats~i و ابزارهای اصلی آن، چرخه حیات به طور خودکار برای شما مدیریت می شود.

به عنوان مثال، اگر از مدیر داده در یک قطعه برای انجام عملیات CRUD استفاده می‌کنید و کاربر از قطعه دور می‌شود، مدیر داده و ابزار درخواست راه دور می‌توانند تمام عملیات شبکه را لغو کنند، از به‌روزرسانی مدیران نمایش صرفنظر کنند. و آنها را لغو ثبت کنید، زیرا قطعه یا پنل نمای شما دیگر وجود ندارد.

گوش دادن به رویدادهای چرخه زندگی

به‌عنوان یک توسعه‌دهنده Oats~i، می‌توانید از یک قطعه یا مدیریت چرخه حیات پانل را مشاهده کنید تا کتابخانه‌های آگاه از چرخه حیات قوی ایجاد کنید که در محیط Oats~i به خوبی کار می‌کنند.

شما فقط باید شی چرخه حیات را با استفاده از روش داخلی بگیرید،

getLifeCycleObject()

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و شنوندگان را به آن متصل کنید. این شنوندگان معمولا شامل چهار روش برای موارد زیر هستند:

onFragmentRunning()

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

زمانی فراخوانی می شود که قطعه ایجاد شده و در حال اجرا باشد

onFragmentCancelled()

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

زمانی فراخوانی می شود که ساخت قطعه لغو شده باشد

onFragmentDestroyed()

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

زمانی فراخوانی می شود که قطعه از بین رفته باشد

onViewReady()

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

زمانی فراخوانی می شود که نمای قطعه به DOM متصل شده باشد

*توجه: *”Fragment” در اینجا برای مشاهده پانل ها نیز اعمال می شود.

فراخوانی های اصلی که باید مراقب آنها باشید عبارتند از: onFragmentRunning()، onViewReady() و onFragmentDestroyed(). اگر کتابخانه شما عملکردی اضافه می‌کند که مرتبط با UI نیست، می‌توانید پس از دریافت فراخوانی ()onFragmentRunning، کتابخانه را فعال کنید.

اگر کتابخانه نماها را دستکاری می کند (مانند کتابخانه انیمیشن)، می توانید عملکرد آن را پس از دریافت فراخوانی ()onViewReady فعال کنید.هنگامی که تماس onFragmentDestroyed() را دریافت کردید، وسایل را جمع کنید و همه چیز را متوقف کنید.

هسته مبتنی بر OOP

ما در مورد برخی از ویژگی های اصلی Oats~i زیاد صحبت کرده ایم، اما در مورد پارادایم صحبت نکرده ایم. کد اصلی Oats~i را چگونه می نویسید؟

خوب، Oats~i یک چارچوب وب مبتنی بر OOP است. این بدان معناست که بیشتر ابزارها به صورت کلاس ارائه می شوند. یک قطعه از یک کلاس AppMainFragment یا AppChildFragment ایجاد می شود. مدیر داده یک کلاس است. نمایش مدیران کلاس ها و غیره هستند.

من OOP را به دلیل قابلیت استفاده مجدد، جمع آوری زباله و روشی بسیار تمیزتر برای مدیریت عملکردها و فرآیندهای درون Oats~i انتخاب کردم.

به عنوان مثال، هیچ جناسی در نظر گرفته نشده است، داشتن قطعه به عنوان یک کلاس به Oats~i اجازه می دهد تا کاری هوشمندانه انجام دهد. اگر تشخیص دهد که دوباره از کلاس قطعه استفاده می شود، هرگز آن را بازسازی نمی کند. درعوض، فرآیند ساخت مستقیماً به اجرای onQueryParamsDataUpdate() می‌رود و نمای اصلی قطعه را دوباره رندر نمی‌کند یا آن بخش از DOM را به‌روزرسانی نمی‌کند، زیرا غیرضروری است.

مزیت دیگر انجام این کار این است که قطعه شما می تواند بخشی از حالت خود را در میان فراخوانی های مسیر مرتبط حفظ کند.

به عنوان مثال، در مورد Verte، هنگامی که در بخشی هستید که یک مقاله وبلاگ را ارائه می‌کند، کلیک کردن روی مقاله دیگری در فهرست «داستان‌های دیگر»، قطعه را بازسازی نمی‌کند. در عوض، نمای اصلی دست نخورده است و تنها نماهای پویا و مبتنی بر داده، که توسط مدیر داده در ارتباط با مدیر view اجرا می‌شوند، بر اساس مقدار پارامتر جدید به‌دست‌آمده از onQueryParamsDataUpdate() به‌روزرسانی می‌شوند.

بهره برداری از برنامه نویسی تابعی

فقط به این دلیل که هسته Oats~i از OOP استفاده می کند، به این معنی نیست که شما کاملاً محدود به ایجاد کتابخانه هایی هستید که از پارادایم OOP پیروی می کنند. به سادگی آگاه کردن آنها از چرخه زندگی کافی است.

این به آن‌ها اجازه می‌دهد تا منابع را به‌عنوان قطعه‌ای که Oats~i رندر می‌کند و از بین می‌برد، آزاد کنند.

هنگام انتقال مشتری Verte به Oats~i، من از این استراتژی دقیق برای استفاده مجدد از برخی از اسکریپت های کاربردی که برای صفحات وب اصلی نوشته بودم استفاده کرده ام.

بنابراین، من انتظار دارم که برای توسعه دهندگانی که به دنبال استفاده از اسکریپت های کاربردی خود در پروژه Oats~i هستند، تنگناها و سختگیری های پارادایم بسیار کمی داشته باشند، تا زمانی که از چرخه حیات آگاه باشند.

رندر سمت سرور (نماها و داده ها)

در نهایت، بخش بزرگی از چارچوب های وب مدرن – رندر سمت سرور.Oats~i به طور بومی از رندر سمت سرور پشتیبانی می کند، بدون نیاز به اجرای جاوا اسکریپت بر روی سرور.

با استفاده از HTMLWebpackPlugin، می‌توانید نماهایی را که برای هر قطعه در برنامه Oats~i خود استفاده می‌کنید، در فایل‌های .html/.hbs خود استخراج کنید که می‌توانید زمانی که مشتری درخواست صفحه‌ای در بارگذاری جدید می‌کند، آن‌ها را برای مشتری ارسال کنید.

تنها مورد نیاز این است که ساختار نمای شما از سرور همان چیزی باشد که برنامه آن را ارائه می‌دهد.

اما هنوز کارمان تمام نشده است.

هیدراتاسیون مدیر داده

نماهایی که از سرور خود ارائه می دهید به احتمال زیاد وضعیتی از داده ها را نشان می دهند. Oats~i چگونه این موضوع را مدیریت می کند و از حالت رندر سمت سرور پیش می رود؟

شما در حالت ایده آل از مدیر داده برای مدیریت نماهای پویا یا مبتنی بر داده در برنامه Oats~i خود استفاده خواهید کرد. اکنون، با استفاده از آن، می‌توانید از هیدراتاسیون سمت سرور استفاده کنید که از یک اسکریپت رندر شده در تگ head از سرور استفاده می‌کند تا به مدیر داده کمک کند تا وضعیت داده‌ها را از سرور درک کند، آن را ذخیره کند، و مدیران نمای پیوستی را نیز به‌روزرسانی وضعیت‌های خود داشته باشد. بر اساس آن، و از آنجا به اجرای برنامه ادامه دهید.

در اینجا نحوه عملکرد آن آمده است.

در قسمت نشانه گذاری خود، در سرور، می توانید یک اسکریپت با فرمت زیر اضافه کنید:

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این اسکریپت اطلاعات مهمی را برای مدیر داده از سرور فراهم می کند که تصویر کامل یا ایده ای از وضعیت داده را به آن می دهد.

هر مدیر داده یک “info_key” خواهد داشت که وضعیت داده خود را از آن می خواند. هنگامی که مدیر داده را تنظیم کردید تا از سمت سرور هیدراته شود، اسکریپت را با شناسه ای که ارائه می کنید پیدا می کند، متغیر در معرض نمایش داده شده DataManagerHydrationInfo را دریافت می کند و مقدار “info_key” را می خواند.

این مقدار باید یک آرایه باشد که در حالت ایده آل از همان نوع مدل مدیر داده است. با این حال، می تواند متفاوت باشد.

به این دلیل که مدیر داده یک فرآیند هیدراتاسیون چند مرحله ای را اجرا می کند.

اعتبار سنجی

خواندن از روی یک اسکریپت می تواند مشکلات و آسیب پذیری های خاص خود را داشته باشد. می توانید قبل از اینکه مدیر داده آن را انجام دهد، یک بررسی اعتبار سنجی روی داده های ذخیره شده در اسکریپت هیدراتاسیون انجام دهید.

پیش پردازش

بسته به منطق کسب و کار و طراحی برنامه وب شما، قالب داده ای که از سرور شما تهیه می شود می تواند با مدلی که در مدیریت داده خود اجرا می کنید متفاوت باشد. مدیر داده Oats~i یک مرحله پیش پردازش اختیاری را در طول هیدراتاسیون اجرا می کند که به شما امکان می دهد داده ها را از هیدراتور به فرمت مدل خود تبدیل کنید.

مرحله شبکه

این مرحله به شما این امکان را می‌دهد که در مورد داده‌هایی که در اسکریپت هیدراتاسیون خود آزاد می‌کنید، محتاط باشید، به روی اسکریپرهای وب، روبات‌ها و موتورهای جستجو باز است.

می‌توانید یک مرحله شبکه اختیاری را اجرا کنید که در آن می‌توانید داده‌های خصوصی یا پنهانی را که مدل مدیر داده‌تان به آن نیاز دارد، دریافت کنید، اما هرگز نباید از اسکراپرهای وب یا روبات‌هایی که وب را می‌شویند، مطلع باشید.

به عنوان مثال، اگر سبد خرید را هیدراته می‌کنید، می‌توانید اسکریپت هیدراتاسیون از سرور فقط حاوی اطلاعات کلی در مورد محصولات باشد، با شناسه‌های عمومی که وقتی به باطن امن شما منتقل می‌شوند، اطلاعات محرمانه بیشتری را که استفاده می‌کنید برمی‌گرداند. برای بررسی کاربر

بنابراین، اسکریپت هیدراتاسیون شما می‌تواند اطلاعاتی را به همان اندازه که قبلاً در html ارائه شده است، در خود نگه دارد، از مدیر داده بخواهید آن را بلافاصله به صورت داخلی انجام دهد، سپس همه چیزهای دیگر را از چرخه شبکه تهیه کنید.

بعدی برای Oats~i چیست؟

اگر تا این لحظه موفق به خواندن شده اید، آفرین، شما یک قهرمان هستید! این بهترین کاری است که می‌توانم انجام دهم تا تقریباً چهار سال کار را در یک پست وبلاگ کوچک «مقدمه‌ای» جمع کنم.

Oats~i یک پروژه یادگیری عظیم برای من بوده است و هم مضطرب و هم هیجان زده هستم تا جامعه فناوری را در مورد آن بدانند. چیزهای زیادی برای باز کردن، آموزش، یادگیری و اشکال زدایی وجود دارد.

برنامه من در حال حاضر این است که متن باز Oats~i. من روی جزئیات کار می‌کنم و امیدوارم در چند روز آینده کل پایگاه کد کاهش پیدا کند و همه ما بتوانیم در آن جستجو کنیم، برنامه‌های وب واقعی را از طریق چارچوب بسازیم، و سرعت آن را بالا ببریم.

در حال حاضر، من از بازخورد، نظرات، و سؤالات شما در مورد Oats~i، در صورت داشتن هرگونه، قدردانی خواهم کرد.وب سایت Verte Environmental Solution را بررسی کنید و آن را در عمل ببینید.

من در لینکدین در دسترس هستم، پس بروید و سلام کنید.

به زودی می بینمت، زمانی که امیدواریم ساختن با Oats~i را شروع کنیم.

ویرایش: کد منبع اکنون عمومی است. https://github.com/Oats-i/Oats-i

لوگوی Oats~i
من حدود پنج سال است که یک توسعه دهنده وب فعال هستم. در اواخر سال 2019، زمانی که من به طور رسمی توسعه وب را شروع کردم، توسط اکوسیستم وسیعی از ابزارهای توسعه وب احاطه شده بودم که می توانستم از آنها برای ایجاد وب سایت برای مشتریان و هر پروژه شخصی که داشتم استفاده کنم.

اما متوجه شدم که مسیر خودت را انجام بده. نه به این دلیل که به لحظات دردناک و دردناک عادت کرده‌ام، بلکه به این دلیل که می‌خواستم توسعه وب را از اصول آن یاد بگیرم، نه اینکه مستقیماً وارد چارچوبی شوم و دانش خود را از آنجا بسازم.

علاوه بر این، این چیزی است که اکثر توسعه دهندگان وب با تجربه توصیه می کنند. HTML، CSS، و جاوا اسکریپت وانیلی را بیاموزید، و هر چیز دیگری که در کنار آن باشد، در پارک بسیار جذاب خواهد بود.

خوب، اینجا هستیم، پنج سال بعد و به نوعی، من یک چارچوب وب برای خودم ساختم. چیزی که به عنوان یک تمرین یادگیری ساده در مورد نحوه کار APIهای وب و وب شروع شد، در نهایت به یک پروژه تمام عیار با لحظات بی‌شماری سر خاراندن، ناامیدی و اورکا تبدیل شد.

معرفی Oats~i، چارچوب وب باز که همچنین شما را به اصول اولیه بازمی گرداند. Oats~i ساختاری را ارائه می دهد که به شما امکان می دهد برنامه های وب را با استفاده از HTML، CSS، و جاوا اسکریپت Vanilla ایجاد کنید، با قابلیت توسعه قدرتمند، رندر سمت سرور، مسیریابی مبتنی بر رضایت، واکنش پذیری از طریق مدیر داده، مدیر نمایش، و قلاب ها، یک قطعه سیستم مشاهده مبتنی بر، مشاهده پنل‌ها برای پشتیبانی از طرح‌بندی‌های اضافی، پنجره‌های بازشو، و نمایش‌های سفارشی در بالای قطعات، پشتیبانی از ویژگی‌های مرور وب «بومی» مانند پارامترها، پرس و جوها، و اهداف، صفحه‌بندی، تقسیم کد و بارگذاری تنبل برای جاوا اسکریپت و مشاهده بسته‌ها

همه اینها به صورت بومی با فریمورک ارائه می‌شوند و در بالای Webpack به عنوان بسته‌کننده ماژول ترجیحی اجرا می‌شوند.

Oats~i به محیط سرور شما اهمیتی نمی دهد زیرا یک سیستم کاملاً مبتنی بر مشتری است. هیچ JS در حال اجرا روی سرور وجود ندارد، بنابراین برای استقرار یک برنامه Oats~i نیازی به راه اندازی سرور خاصی نیست.

اما قبل از اینکه به جزئیات بپردازیم، اکنون کجا اجرا می شود؟

اینجا: https://www.vertesolutions.com

آن سایت یک سایت تولیدی برای مشتری است که در زمینه مشاوره زیست محیطی و تجارت زیست محیطی فعالیت می کند. این کسب و کار Verte Environmental Solutions نامیده می شود، بنابراین اگر متوجه شدید که من به «وب سایت Verte» اشاره می کنم، این همان سایتی است که به آن اشاره می کنم.

Oats~i در حال حاضر در هیچ جای دیگری اجرا نمی شود.

ویرایش: کد منبع نیز عمومی است. https://github.com/Oats-i/Oats-i

قبل از رسیدن به این نقطه، من در طول سال ها در حال توسعه چارچوب در پنل مدیریت سایت (که سفارشی ساخته شده است)، آزمایش، به روز رسانی و افزودن ویژگی های جدید بوده ام. بنابراین، اگر برخی از مواردی که در اینجا در سایت مشتری در مورد آنها صحبت خواهم کرد را از دست دادید، مطمئن شوید که آنها روی ادمین اجرا می شوند.

همچنین، چیزی که من معرفی می‌کنم یک چارچوب نسبتاً کامل است، با چند ویژگی برای صحبت در مورد. بنابراین هشدار دهید، این یک قطعه طولانی خواهد بود. و من سعی کردم تا آنجا که می توانم آن را ویرایش کنم تا کوتاهتر شود. با این حال، من با این مقدمه به اصل همه چیز دست زدم. بقیه قسمت قبل از اینکه در پست‌های بعدی عمیق‌تر شویم، یک خراش از سطح است.

پس این مقدمه بس است.

بیایید کمی عمیق‌تر به Oats~i بپردازیم، همانطور که تا به حال آن را ساخته‌ام، و به برخی از مواردی که در خارج از جعبه ارائه می‌دهد و برنامه‌ریزی‌هایی که برای حرکت رو به جلو دارد، نگاه کنیم.

یک چارچوب وب باز

با نامیدن Oats~i یک چارچوب وب باز، منظورم این است که Oats~i یک چارچوب ساده و در عین حال قابل توسعه است که کد آن را می توان با HTML ساده و جاوا اسکریپت Vanilla نوشت، البته CSS ابزار یک ظاهر طراحی واقعی است. از این راه‌اندازی ساده، می‌توانید موتورهای قالب، کتابخانه‌های css و ابزارهای دیگر، شخص ثالث یا سفارشی خود را اضافه کنید، تا زمانی که Webpack به آن اجازه دهد و بتوانید آن را پیکربندی کنید.

سیستم مبتنی بر قطعه

Oats~i از طریق یک سیستم ساخت کار می کند که قطعات را به عنوان “کامپوننت” یا قطعات اصلی برنامه وب ایجاد می کند. به عنوان مثال این نماهای ساده را در نظر بگیرید:

توضیحات تصویر

توضیحات تصویر

هر دو تصویر دارای “نمای ریشه” برنامه هستند که نمای اصلی برنامه است که کاربر همیشه خواهد دید. سپس نماهای دیگر (قطعات) به صورت پویا در داخل ارائه می شوند.

توضیحات تصویر

توضیحات تصویر

نمای ریشه می‌تواند شامل پیوندها یا دکمه‌های پیمایش اصلی و سایر نماهایی باشد که کاربر همیشه در برنامه مشاهده می‌کند و معمولاً تغییر نمی‌کند.

بقیه نماهای داخل نمای ریشه تغییر خواهند کرد، و این بر اساس بارگیری و بارگیری قطعات از برنامه، بر اساس مسیریابی کاربر است. فرگمنت ها از طریق یک فرآیند ساخت گذر می کنند که در درجه اول نمای مورد نظر را دریافت می کند، آن را در گره والد هدف قرار می دهد و سپس به شما امکان می دهد بقیه برنامه و منطق تجاری خود را سیم کشی کنید.

یک فرآیند ساخت Oats~i معمولاً متدهای اصلی زیر را در قطعه شما فعال می کند:

//gets the view for your fragment
async initializeView(cb){
}

//triggers after the fragment view has been attached to the DOM
onUIBind(serverSideRendered){
}

//triggers after the fragment has completed building and anytime its rebuilt for the same route
async onQueryParamsDataUpdate(changedParams, data, savedState, routeParams, isServerSide){
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و اساساً همین است.

با چنین ساختار اسکلتی شما چند انعطاف دارید، مانند:

ارائه HTML ساده یا بارگیری نماهای پیچیده با استفاده از موتورهای قالب (به انتخاب شما)

اولین روشی که باطل می کنید (initializeView()) را می توان به صورت زیر تکمیل کرد:

async initializeView(cb){

  const viewAsString = `

My view

`; this.onViewInitSuccess(viewAsString, cb); }
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نمای خود را به عنوان یک رشته HTML دریافت می کنیم و آن را به متد داخلی (onViewInitSuccess()) ارسال می کنیم که همچنین callback ارسال شده به متد اصلی را نیز می گیرد.

فراخوانی ()onViewInitSuccess فرآیند ساخت را برای ادامه مراحل بعدی آغاز می کند.

نوشتن HTML به‌عنوان یک رشته در JS ساده است و Oats~i اجازه می‌دهد، اما اغلب ممکن است مشکل ساز شود. با این حال، به جای ساختن یک نحو یا سیستم جدید برای نوشتن نماها برای Oats~i، Oats~i به شما این امکان را می‌دهد تا هر موتور قالبی را که برای مورد استفاده شما بهتر کار می‌کند، وصل کنید، آن را در پیکربندی بسته وب خود سیم‌کشی کنید و اجازه دهید جادویی خود را انجام دهد. .

در مورد Verte، من از handlebars ترکیب شده با handlebars-loader برای نوشتن فایل‌های view جداگانه با فرمت hbs استفاده می‌کنم و به سادگی آن‌ها را در کد خود مورد نیاز می‌دانم.

بنابراین، به جای

const viewAsString = `

My view

`;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

دیدگاه های من اکنون به صورت زیر ارائه می شود:

const viewAsString = require("./relative/path/to/view.hbs")(myTemplatingData);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

به عنوان مثال، اگر بخواهم به جای آن از ejs استفاده کنم، فقط باید پیکربندی بسته وب خود را به روز کنم و از دستور واردات مناسب برای آن مورد استفاده کنم.

Oats~i فقط اهمیت می دهد که نمای ارسال شده به آن یک رشته HTML باشد.

نماهای منبع یابی شبکه

Oats~i تا جایی پیش می رود که به شما امکان می دهد بازدیدهای خود را از طریق شبکه منبع کنید. تا حدی به همین دلیل است که async در متد ()initializeView وجود دارد.

Oats~i همچنین از شما انتظار دارد که احتمالاً در این مرحله تماس های شبکه ای برقرار کنید، یا برای یک نمای کامل بر اساس نوع کاربر یا سایر عوامل، یا داده های قالب را بر اساس دیدگاه و منطق تجاری خود دریافت کنید.

کاری که در اینجا انجام می دهید کاملاً به دلایل تجاری و فنی شما بستگی دارد.

**نکته: **دلیل خوبی وجود دارد که چرا سیستم ساخت منتظر وعده‌ها در مرحله ساخت برای حل با استفاده از await یا then() نمی‌ماند، بلکه در عوض از یک callback ارسال شده به متدهای مربوطه استفاده می‌کند. این زمانی مشخص خواهد شد که در قسمت بعدی به بررسی نحوه عملکرد Oats~i بپردازیم.

Vanilla JavaScript یا یک کتابخانه JS سازگار برای برنامه یا منطق تجاری

کد Oats~i در جاوا اسکریپت وانیلی است که مرورگرهای وب زبان “بومی” آن را درک می کنند. با این حال، چند انعطاف وجود دارد که می توانید هنگام نوشتن منطق کسب و کار خود داشته باشید.

به عنوان مثال، به هر دلیلی می توانید jQuery را در پروژه خود پورت کنید و از آن برای نوشتن بخشی از منطق خود استفاده کنید. من در واقع این کار را مدتها قبل انجام دادم، حتی قبل از اینکه Oats~i به وضعیت فعلی خود ساخته شود، تا حدود پنج خط کد برای افکت های اسکرول صاف در وب سایت Verte بنویسم. (TLDR، من تنبل بودم که فراتر از Stack Overflow فکر کنم، lol).

از نظر تئوری می‌توانید از Oats~i در محیط TypeScript استفاده کنید، اما هنوز این مورد را آزمایش نکرده‌ام. تنها استفاده ای که از تایپ اسکریپت داشتم، سیستم تایپ آن، همراه با JSDocs، برای مستندسازی انواع در چارچوب بود، روشی که مدتی قبل مستندسازی کردم.

می‌توانید در مورد ادغام JSDocs و TypeScript برای اهداف تایپ، بدون فرآیند ساخت، اینجا بخوانید.

تقسیم کد و بارگذاری تنبل

Webpack یک ابزار توسعه وب قدرتمند است که امکان پیکربندی پروژه های بسیار پیچیده را فراهم می کند و به تیم های توسعه انعطاف پذیری لازم را برای ساخت یک پروژه با مشخصات منحصر به فرد آن می دهد.

Oats~i در بالای Webpack اجرا می‌شود، با چارچوبی که اساساً به ویژگی تقسیم کد و بارگذاری تنبل Webpack برای پشتیبانی از تکه‌ها و بسته‌های قطعه ناهمگام متکی است.

این بدان معنی است که قطعات شما می توانند در یک بسته بارگذاری شوند یا با استفاده از بسته وب به چند تکه تقسیم شوند و سرعت بارگذاری اولیه برای برنامه وب Oats~i شما بهینه شود. اگر برنامه شما به آن‌ها نیاز دارد، این را با نماهای منبع شبکه مرتبط کنید، و راه‌های متعددی وجود دارد که می‌توانید برنامه خود را در Oats~i بهینه کنید تا از بهترین تجربه کاربر در مورد زمان بارگذاری اطمینان حاصل کنید.

تنظیمات پیشرفته پروژه با استفاده از Webpack

شاید بزرگترین مزیت داشتن وب پک به عنوان پایه Oats~i پیکربندی بزرگی است که در اختیار شما گذاشته شده است که به شما امکان می دهد برنامه خود را همانطور که به آن نیاز دارید بسازید.

به همین دلیل است که می‌توانید موتورهای قالبی را تنظیم کنید که مطابق با فرآیند رندر نمایش شما باشد، babel و سایر لودرها/افزونه‌ها را برای برنامه خود پیکربندی کنید، و به سادگی چیزی بسازید که کاملاً با مشخصات پروژه شما مطابقت داشته باشد.

Oats~i یک پیکربندی پایه وب بسته ساده را اجرا می کند که برای ایجاد نماها یا قالب های سمت سرور شما، handlebars-loader، html-loader، css loader، asset loader و HTMLWebpackPlugin را راه اندازی می کند. با استفاده از webpack-merge، می توانید این پیکربندی ها را گسترش دهید و برنامه وب خود را همانطور که می خواهید معماری کنید.

این باعث می شود Oats~i بسیار شبیه یک سیستم plug-and-play عمل کند. این یک اسکلت به شما می دهد و می توانید برنامه خود را به دلخواه دور آن بپیچید و پیکربندی کنید.

مسیریابی

مسیریابی یک ویژگی پیش فرض در Oats~i است. در واقع، برای اجرای برنامه، باید اطلاعات مسیریابی را ارائه دهید که برنامه از آن برای مقداردهی اولیه خود و مدیریت ناوبری کاربر و رندر قطعه استفاده می کند.

اطلاعات مسیریابی ساده به این صورت است:

Const MyRoutingInfos = [
  {
    route: "/my-route",
    target: myMainFragmentBuilder,
    nestedChildFragments: [
      myNestedChildFragmentBuilder
    ]
  }
]
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

هنگامی که Oats~i از سرور بارگیری می‌شود، آدرس اینترنتی فعلی را بررسی می‌کند و در اطلاعات مسیریابی ارائه شده مطابقت با آن پیدا می‌کند. در مورد Verte، وقتی «https://dev.to/» را بارگیری می‌کنید، Oats~i اطلاعات مسیریابی را با آن مسیر به‌عنوان همسان جستجو می‌کند و سپس قطعات را به ترتیب از «هدف» به هر قطعه فرزند تودرتو باد می‌کند.

همچنین می‌توانید یک مسیر پیش‌فرض ارائه کنید که Oats~i سعی می‌کند برنامه را از آن راه‌اندازی کند، مگر اینکه مشتری صفحه را از مسیر معتبری که در اطلاعات مسیریابی شما آمده است، تهیه کرده باشد.

پارامترها در مسیریابی

Oats~i همچنین از استفاده از پارامترها در مسیرها، با استفاده از نحو کولون که معمولاً در express استفاده می‌شود، پشتیبانی می‌کند.

بنابراین، مسیری که مانند /:myParams تعریف شده است معتبر است و برای مسیرهایی مانند /user-1، /user-2، /user-3 نقشه‌برداری می‌کند.

Oats~i یک قدم جلوتر می رود و این پارامترها را برای شما تجزیه می کند.
هنگام تنظیم قطعه خود، گزینه تنظیم پارامترهایی را دارید که باید مراقب آنها باشد. نام پارامتر باید دقیقاً با نام استفاده شده در اطلاعات مسیریابی شما مطابقت داشته باشد.

هنگام ساخت قطعه، Oats~i مقدار را تجزیه می کند، هر گونه تغییر را یادداشت می کند و دو آرگومان را به متد ()onQueryParamsDataUpdate شما ارسال می کند. اینها موضوعی از همه پارامترهای تماشا شده هستند که تغییر کرده اند، و مقدار فعلی همه پارامترهای تماشا شده.

بنابراین، اگر قطعه ای دارید که اطلاعات کاربر را نشان می دهد، که در مسیر /:userID تعریف شده است، و مشتری ابتدا به /user-xyz هدایت می شود، می توانید مقدار userID را به عنوان user-xyz بخوانید. اگر کلاینت دوباره مسیر یابی کند و این بار مسیر /user-abc باشد، بلافاصله متوجه خواهید شد که مقدار userID به user-abc تغییر کرده است و می توانید به طور مناسب پاسخ دهید.

پشتیبانی پرس و جو

پرس و جوها همچنین بخش اصلی وبگردی و آدرس های اینترنتی هستند. Oats~i همچنین پرس‌و‌جوها را برای شما تجزیه می‌کند، به شرطی که به قطعه بگویید آنها را با استفاده از کلیدهایشان تماشا کند.

به عنوان مثال، اگر مسیر /:userID شما به /user-3?promptUpgrade=true نگاشت شود، و در قطعه خود مشخص کنید که می خواهید به روز رسانی های درخواست را با کلید “promptUpgrade” مشاهده کنید، آنها تجزیه و به قسمت ارسال می شوند. روش onQueryParamsDataUpdate() نیز هست.

با این حال:

شما نمی توانید با استفاده از پرس و جو، مسیرها را در اطلاعات مسیریابی خود بنویسید. فقط پارامترها پشتیبانی می شوند. Oats~i به دنبال اطلاعات مسیریابی معتبر برای یک url معین پس از کوتاه کردن هرگونه پرسش و هدف می‌گردد. تجزیه و تحلیل پس از آن انجام می شود.

وب‌سایت Verte در حال حاضر از این مکانیسم هنگام نمایش نماها برای مقالات وبلاگ در صفحه مقاله وبلاگ استفاده می‌کند. مسیر برای هر مقاله پارامتری است و ما فقط به تغییر در پارامتر تماشا شده پاسخ می دهیم.

مسیریابی مبتنی بر رضایت

این شاید یک ویژگی بسیار منحصر به فرد از Oats~i باشد. مسیریابی مبتنی بر رضایت به شما قدرت تجربه کاربر را می‌دهد و به شما این امکان را می‌دهد که در صورت وجود هر گونه فرآیند معلقی که همه در برنامه کنترل می‌شوند، به کاربران در مورد دور شدن از یک صفحه مهم هشدار دهید.

Oats~i به جای استفاده از API استاندارد مرورگر ارائه شده که یک کادر محاوره ای را باز می کند، از ترکیبی از History API و مدیریت حالت برای تشخیص پاپ یا پیمایش استفاده می کند، از قطعات رندر شده فعلی درخواست رضایت می کند، تلاش های پیمایش بعدی را متوقف می کند و فقط ادامه می دهد. اگر کاربر به آن اجازه دهد.

اگر کاربر انتخاب کند که در نمای فعلی خود باقی بماند، Oats~i مسیر ناوبری مرورگر را به حالت اولیه بازیابی می کند.

البته، اینکه کاربران هر بار که می خواهند در برنامه شما حرکت کنند، روی “ok” کلیک کنند، ایده بدی است. بنابراین، به‌طور پیش‌فرض، قطعات Oats~i و پانل‌های مشاهده (در ادامه در مورد آنها بیشتر توضیح خواهیم داد) به طور پیش‌فرض با تلاش ناوبری موافقت می‌کنند.

Verte به صورت داخلی از این برای محافظت از سرپرست هنگام مدیریت محتوای وبلاگ استفاده می کند، در صورتی که پیش نویس فعلی هنوز توسط اسکریپت ذخیره خودکار در دلتای زمانی خود انتخاب نشده باشد. در صورتی که سرپرست بخواهد از ویرایشگر وبلاگ دور شود و پیش‌نویس‌های ذخیره‌نشده وجود داشته باشد، از طریق یک گفتگو اخطاری دریافت می‌کنند و انتخاب می‌کنند که به پیمایش دور ادامه دهند یا در صفحه بمانند و کار خود را به صورت دستی ذخیره کنند.

پنجره‌های بازشو، دیالوگ‌ها و طرح‌بندی‌های بیشتر با استفاده از پنل‌های نمایش

در Oats~i، چارچوب در درجه اول یک مسیر را از طریق قطعات ارائه می کند. با این حال، یک ابزار اضافی به نام view panels وجود دارد که به شما امکان می دهد نماهای دیگری را که ممکن است قطعه شما ممکن است به آن نیاز داشته باشد ارائه دهید. اینها شامل کادرهای گفتگو، پانل های همبرگر یا حتی بارگذاری صفحه نمایش با اطلاعات سفارشی است که ممکن است کاربر به آن نیاز داشته باشد.

برای ایجاد یک پنل نمایش، باید آن را از طریق مدیر پنل های نمایش درخواست کنید. Oats~i خود نماها را برای قطعات و پانل‌های مشاهده مدیریت می‌کند، به این معنی که شما هرگز مجبور نیستید منطق بنویسید تا نماهای قطعه اصلی خود را به DOM متصل کنید یا زمانی که پانل view یا قطعه مرتبط با آن به دلیل تغییر در ناوبری از بین رفت، آنها را حذف کنید.

یک پنل نمایش که توسط مدیر پنل‌های مشاهده ایجاد می‌شود نیز به‌طور خودکار به فرآیند مسیریابی رضایت قطعه متصل می‌شود و به شما امکان می‌دهد عملکرد قطعه را گسترش دهید.

نمایش پانل ها همچنین می توانند پارامترها و پرس و جوها را تماشا کنند.

پانل‌های مشاهده مسیر راه‌اندازی و مستقیم

پانل‌های مشاهده را می‌توان با تغییر مسیر یا مستقیماً از طریق تماس با مدیر پنل‌های نمای قطعه فعال کرد. برای اولی، این جایی است که داشتن پرس و جو در مسیر شما و پیوند آنها به یک پنل مشاهده در قطعه می تواند مفید باشد.

اگر مسیری دارید “/:post-id” که در حال حاضر در مرورگر به صورت “/nice-post?showComments=true” نمایش داده می شود، می توانید از پانل مشاهده مسیر راه اندازی شده در قطعه استفاده کنید تا به طور خودکار یک پانل جانبی ظاهر شود. نظرات پست را بارگذاری می کند و به کاربر اجازه می دهد آنها را بخواند.

این ویژگی معمولاً از طریق متد ()onQueryParamsDataUpdate قابل دسترسی است. فراخوانی super (در صورتی که آن را لغو کرده باشید) مدیر پانل‌های نمای قطعه را فراخوانی می‌کند تا هر پانل نمای راه‌اندازی مسیر را ارائه کند.

بزرگترین مزیت این نوع تنظیم این است که رندر و رفتار پنل نمای شما اکنون به ناوبری گره خورده است و تجربه کاربر را طبیعی تر می کند.

بنابراین، با توجه به مثال ما، اگر کاربر به “/nice-post?showComments=true” پیمایش کند، نظرات را بخواند و به عقب فشار دهد، مسیر به “/nice-post” تغییر خواهد کرد، مدیر پنل های نمایش این را یادداشت می کند. تغییر دهید، و تا زمانی که رضایت داده شده باشد، به طور خودکار فرآیند تخریب پانل نمایش را آغاز می کند.

درست مانند قطعات، پنل‌های مشاهده نیز به‌طور پیش‌فرض رضایت می‌دهند. بنابراین، فقط در صورت لزوم باید روش رضایت را لغو کنید.

واکنش پذیری و مدیریت داده ها

یک چارچوب وب مدرن بدون لمس خوبی از واکنش پذیری و مدیریت داده کامل نمی شود. و اینجاست که شاید مهم‌ترین تفاوت بین Oats~i و سایر چارچوب‌های وب ظاهر می‌شود.

Oats~i به طور خودکار نماها را به یک داده یا حالت جفت نمی کند.

در عوض، این به طور کامل به توسعه دهنده واگذار می شود تا آن را بر اساس برنامه یا منطق تجاری خود انجام دهد.

همانطور که هست، می‌توانید از Oats~i برای ساختن یک برنامه وب با چندین صفحه استاتیک که در زیر قطعات رندر شده‌اند و پانل‌ها را مشاهده کنید، استفاده کنید و آن را در آن پایان دهید. برنامه فقط کار خواهد کرد. اگر می‌خواهید داده‌ها، تماس‌های شبکه و واکنش‌پذیری را اضافه کنید، ابزار مدیریت داده همه چیز را پوشش می‌دهد، و تنها تا محدوده‌ای که شما تعیین می‌کنید، بدون تأثیر بر روی نماها یا داده‌های اطراف.

بیایید به مدیر داده و ابزارهای پشتیبانی آن نگاه کنیم: رابط شبکه و مدیران مشاهده.

مدیر داده ها

مدیر داده یک ابزار Oats~i است که به شما امکان می دهد داده ها، منابع سرور و نماهای کلاینت را با هم گره بزنید. مدیر داده مجموعه‌ای از مدل‌ها را نگه می‌دارد، یک مدل قطعه اصلی یا نوع داده مرتبط با بخشی از برنامه شما و نماهای انتخابی آن است.

در حال حاضر، من آن را طوری طراحی کرده‌ام که یک مدل را به‌عنوان یک شی با آرایه‌های تو در تو در نظر بگیرم، زیرا رایج‌ترین فرمت برای انتقال داده‌ها به منابع مشتری و سرور (به عنوان Json) است.

بنابراین، یک مدل ساده می تواند چیزی شبیه به این باشد:

{
  my: string,
  simple: number,
  obj: {
    ofArrays: number[],
    objArrays: { objKey: string }[]
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

مدیر داده با تعیین محدوده مدل خود کار می کند. این بدان معنی است که هر بیت از مدل را می توان به عنوان یک واحد در نظر گرفت و مجموعه ای از کلیدهای جدا شده از نقطه را ایجاد می کند که مقدار یا نوع خاصی را در داده های شما تعریف می کند.

به عنوان مثال، در مثال بالا، مدیر داده مدل را به حوزه های زیر تقسیم می کند: “MODEL_ROOT | my | ساده | obj | obj.ofArrays | obj.objArrays | obj.objArrays.array.objKey “

این دامنه ها نشان دهنده:

MODEL_ROOT -> {
  my: string,
  simple: number,
  obj: {
    ofArrays: number[],
    objArrays: { objKey: string }[]
  }
}

my -> string,

simple -> number

obj -> {
  ofArrays: number[],
  objArrays: { objKey: string }[]
}

obj.ofArrays -> number[]

obj.objArrays -> { objKey: string }[]

obj.objArrays.array.objKey -> string

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

می‌توانید این محدوده‌ها را به‌عنوان مسیرهای جداشده نقطه‌ای برای یک قطعه داده مجزا در نظر بگیرید.

با استفاده از این حوزه‌ها، مدیر داده‌ها سپس به شما، توسعه‌دهنده، کنترل دقیق داده‌های شما را می‌دهد که به هر یک از این داده‌ها اجازه اختصاص یک رابط شبکه یا مشاهده مدیر(ها) می‌دهد.

بیایید به طور سطحی به بررسی این دو بپردازیم.

توضیحات تصویر

رابط شبکه

در اکثر برنامه‌ها (بومی یا وب)، داده‌هایی که به کاربر نشان داده می‌شوند از یک منبع خارجی، یک سرور، منبع می‌شوند. بنابراین، مدل داخلی اغلب به یک رابط API نیاز دارد که بین خود و منبع خارجی قرار گیرد.

در مورد Oats~i، رابط شبکه عملیات CRUD مورد نیاز شما را در رابطه با داده های نگهداری شده توسط مدیر داده انجام می دهد و اطمینان حاصل می کند که هر دو طرف همگام هستند.

رابط شبکه به عنوان یک شی با سه روش تعریف می شود:

getReqBody()
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این متد بدنه درخواست و سایر داده ها مانند متد، آدرس، هدر و غیره را دریافت می کند.

onDataLoadPostProcess()
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

از آنجایی که نوع داده‌های پاسخ و نوع مدل داخلی شما ممکن است متفاوت باشد، رابط شبکه به شما امکان می‌دهد پاسخ را پس‌پردازش کنید و داده‌های نهایی را در نوع مدل مدیر داده ارائه کنید.

onDataLoadError()
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این روش به شما امکان می دهد در صورت عدم موفقیت تماس شبکه، پاسخ خطا را فرمت کنید.

محدوده رابط شبکه

طراحی های API متنوع هستند، به این معنی که آدرس ها یا مسیرهای مورد استفاده برای انجام عملیات CRUD برای یک قطعه داده معین می تواند متفاوت باشد.

به عنوان مثال، یک برنامه رسانه اجتماعی می تواند یک API متفاوت برای بارگیری همه پست ها داشته باشد و هر پست دارای API های منحصر به فردی برای ارسال مجدد، لایک یا گزارش پست باشد.

با فرض چنین معماری، استفاده از محدوده در مدیریت داده به شما اجازه می دهد تا رابط های شبکه منحصر به فردی را برای هر محدوده مشخص کنید.

به عنوان مثال، می‌توانید یک رابط شبکه برای تماس شبکه MODEL_ROOT (که پست‌ها را بارگیری می‌کند)، تماس شبکه “repost” و هر تماس دیگری که می‌تواند خارج از ساختار مدلی که مدیر داده نگه می‌دارد، داشته باشید.

این به شما یک روش منحصربفرد برای مشاهده داده‌هایتان می‌دهد، آن‌ها را از یک منبع بزرگ با یک نقطه پایان مشترک به مجموعه‌ای از چندین واحد داده که می‌توان به طور مستقل از طریق مدیر داده مدیریت کرد، تجزیه کرد.

نکته کلیدی که در اینجا باید به آن توجه داشت این است که شما فقط می توانید یک رابط شبکه در هر محدوده داشته باشید، و یک “نقطه پایانی” واحد برای هر قطعه داده با محدوده در مدل خود ایجاد کنید.

مشاهده مدیر

از طریق رابط شبکه، مدیر داده اکنون می تواند داده ها را بین مدل خود و سرور همگام نگه دارد. حالا در مورد نمایش آن به کاربر و مهمتر از آن نشان دادن زمانی که در حال تغییر است، چطور؟

اینجاست که view manager وارد می شود.

مشاهده مدیران به جهش‌ها یا تغییراتی که در داده‌های نگهداری شده توسط مدیر داده اتفاق می‌افتد، از طریق عملیات شبکه یا تغییر مستقیم درون برنامه پاسخ می‌دهند.

Oats~i در حال حاضر از دو نوع view manager پشتیبانی می کند – یک مدیر نمای استاندارد و یک مدیر نمای لیست.

یک مدیر نمای استاندارد برای نماهای ساده با مؤلفه هایی که روی یک لیست کپی نشده اند ایده آل است. از سوی دیگر، یک مدیر نمای لیست برای نماهای “پیچیده” با اجزای view کپی شده روی یک لیست بهترین است.

صرف نظر از نوع، یک مدیر view تغییرات زیر را در یک مدل یا انواع محدوده آن به شما می گوید:

onMutate()
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این روش زمانی فعال می شود که یک نوع داده از محدوده در حال تغییر است

onCommit()
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این روش زمانی فعال می شود که یک جهش در نوع داده محدوده تکمیل شده باشد، بنابراین انجام می شود

onCancel()
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این روش زمانی فعال می شود که جهشی از نوع داده محدوده لغو شده باشد

onError()
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این روش زمانی فعال می شود که یک جهش از نوع داده محدوده با خطا مواجه شده باشد و به شما امکان می دهد دوباره امتحان کنید.

همچنین مجموعه‌ای از متدهای سازنده وجود دارد که به شما امکان می‌دهد یک نما (به عنوان یک رشته HTML) پر از داده‌های خود را منتقل کنید. این روش ها همچنین بسته به جهش، به شما اطلاع می دهند که چه زمانی نما متصل شده یا در شرف جدا شدن است.

این سه روش عبارتند از:

inflateRoot()
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نمای قالب را به عنوان رشته ای برای داده های ارائه شده دریافت می کند

onViewAttach()
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

زمانی تماس می گیرد که نما به DOM متصل شده باشد

onViewDetach()
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

زمانی که نمای در شرف جدا شدن از DOM است تماس می گیرد
نتایج این تعاملات را می توانید در صفحات وبلاگ وب سایت Verte مشاهده کنید.

با استفاده از ترکیبی از روش‌های سازنده، قلاب‌های ریشه، و قلاب‌های مؤلفه، نماهای پویا مبتنی بر داده از بخش‌های مقاله وبلاگ و وبلاگ می‌توانند انیمیشن‌های بارگیری را هنگامی که داده‌ها را از شبکه منبع‌یابی می‌کنیم نشان دهند، پیام‌های خطا را در صورت خرابی نشان دهند. و پس از تکمیل داده های جدید از رابط شبکه، نماها را پر کنید.

یک مدیر نمایش همچنین دارای قلاب‌های مؤلفه‌ای خواهد بود که امکان واکنش‌پذیری دانه‌بندی‌شده حتی با عناصر هر گره مشاهده را فراهم می‌کند.

به عنوان مثال، با استفاده از مدل:

{
  my: string,
  simple: number,
  obj: {
    ofArrays: number[],
    objArrays: { objKey: string }[]
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و یک مدیر نمای دامنه “MODEL_ROOT” (بنابراین کل مدل)، می توانیم فرض کنیم که مولفه نمای اصلی که داده های محدوده MODEL_ROOT را نشان می دهد، دارای اجزایی در داخل خود است که من داده های خاص موجود در “my” را نشان می دهد، ” ساده، «obj»، یا به طور کلی دامنه های فرزند MODEL_ROOT.

بنابراین، می توانید یک جزء یا عنصر از دیدگاه خود را تنظیم کنید تا به تغییرات این مقادیر “کودکی” واکنش نشان دهد.

همه این روش‌های hook یک پارامتر viewNode دریافت می‌کنند که توسط view manager به آنها ارسال می‌شود، بنابراین شما همیشه مرجعی دارید که این تغییرات داده‌ها با کدام گره view مرتبط است و اجزای آن را در صورت نیاز جستجو کنید.

با این حال، زمانی که دیگر نیازی به این عناصر نمای اصلی نیستند، نباید خود را به خود زحمت دهید. مدیر view این کار را برای شما انجام می دهد.

بدون DOM مجازی

Oats~i از طریق DOM مجازی عمل نمی کند. درعوض، قطعات، پنل‌های مشاهده، و مدیران مشاهده مستقیماً از APIهای DOM برای درج یا حذف عناصر DOM استفاده می‌کنند.

پس از درج کامپوننت view خود در DOM، مدیر view مرجع مستقیم آن را در قلاب های سازنده، ریشه و کامپوننت در اختیار شما قرار می دهد. بنابراین، می‌توانید مستقیماً شنونده‌ها را اضافه کنید، ویژگی‌ها را تغییر دهید یا به سادگی عنصر DOM را با استفاده از apis DOM مستقیم دستکاری کنید.

مدیریت چرخه حیات

بخش اصلی یک برنامه وب پیچیده مدیریت چرخه حیات است. Oats~i فرآیند مدیریت چرخه حیات خود را برای قطعات و پنل‌های مشاهده دارد، که عملکردهای آن به ابزارهای دیگر مانند مدیر داده، مدیران مشاهده و درخواست از راه دور گسترش می‌یابد (ابزار واقعی که مدیر داده در ارتباط با رابط شبکه از آن استفاده می‌کند. برقراری تماس های شبکه).

بنابراین، مستقیماً با استفاده از Oats~i و ابزارهای اصلی آن، چرخه حیات به طور خودکار برای شما مدیریت می شود.

به عنوان مثال، اگر از مدیر داده در یک قطعه برای انجام عملیات CRUD استفاده می‌کنید و کاربر از قطعه دور می‌شود، مدیر داده و ابزار درخواست راه دور می‌توانند تمام عملیات شبکه را لغو کنند، از به‌روزرسانی مدیران نمایش صرفنظر کنند. و آنها را لغو ثبت کنید، زیرا قطعه یا پنل نمای شما دیگر وجود ندارد.

گوش دادن به رویدادهای چرخه زندگی

به‌عنوان یک توسعه‌دهنده Oats~i، می‌توانید از یک قطعه یا مدیریت چرخه حیات پانل را مشاهده کنید تا کتابخانه‌های آگاه از چرخه حیات قوی ایجاد کنید که در محیط Oats~i به خوبی کار می‌کنند.

شما فقط باید شی چرخه حیات را با استفاده از روش داخلی بگیرید،

getLifeCycleObject()
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و شنوندگان را به آن متصل کنید. این شنوندگان معمولا شامل چهار روش برای موارد زیر هستند:

onFragmentRunning()
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

زمانی فراخوانی می شود که قطعه ایجاد شده و در حال اجرا باشد

onFragmentCancelled()
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

زمانی فراخوانی می شود که ساخت قطعه لغو شده باشد

onFragmentDestroyed()
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

زمانی فراخوانی می شود که قطعه از بین رفته باشد

onViewReady()
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

زمانی فراخوانی می شود که نمای قطعه به DOM متصل شده باشد

*توجه: *“Fragment” در اینجا برای مشاهده پانل ها نیز اعمال می شود.

فراخوانی های اصلی که باید مراقب آنها باشید عبارتند از: onFragmentRunning()، onViewReady() و onFragmentDestroyed(). اگر کتابخانه شما عملکردی اضافه می‌کند که مرتبط با UI نیست، می‌توانید پس از دریافت فراخوانی ()onFragmentRunning، کتابخانه را فعال کنید.

اگر کتابخانه نماها را دستکاری می کند (مانند کتابخانه انیمیشن)، می توانید عملکرد آن را پس از دریافت فراخوانی ()onViewReady فعال کنید.
هنگامی که تماس onFragmentDestroyed() را دریافت کردید، وسایل را جمع کنید و همه چیز را متوقف کنید.

هسته مبتنی بر OOP

ما در مورد برخی از ویژگی های اصلی Oats~i زیاد صحبت کرده ایم، اما در مورد پارادایم صحبت نکرده ایم. کد اصلی Oats~i را چگونه می نویسید؟

خوب، Oats~i یک چارچوب وب مبتنی بر OOP است. این بدان معناست که بیشتر ابزارها به صورت کلاس ارائه می شوند. یک قطعه از یک کلاس AppMainFragment یا AppChildFragment ایجاد می شود. مدیر داده یک کلاس است. نمایش مدیران کلاس ها و غیره هستند.

من OOP را به دلیل قابلیت استفاده مجدد، جمع آوری زباله و روشی بسیار تمیزتر برای مدیریت عملکردها و فرآیندهای درون Oats~i انتخاب کردم.

به عنوان مثال، هیچ جناسی در نظر گرفته نشده است، داشتن قطعه به عنوان یک کلاس به Oats~i اجازه می دهد تا کاری هوشمندانه انجام دهد. اگر تشخیص دهد که دوباره از کلاس قطعه استفاده می شود، هرگز آن را بازسازی نمی کند. درعوض، فرآیند ساخت مستقیماً به اجرای onQueryParamsDataUpdate() می‌رود و نمای اصلی قطعه را دوباره رندر نمی‌کند یا آن بخش از DOM را به‌روزرسانی نمی‌کند، زیرا غیرضروری است.

مزیت دیگر انجام این کار این است که قطعه شما می تواند بخشی از حالت خود را در میان فراخوانی های مسیر مرتبط حفظ کند.

به عنوان مثال، در مورد Verte، هنگامی که در بخشی هستید که یک مقاله وبلاگ را ارائه می‌کند، کلیک کردن روی مقاله دیگری در فهرست «داستان‌های دیگر»، قطعه را بازسازی نمی‌کند. در عوض، نمای اصلی دست نخورده است و تنها نماهای پویا و مبتنی بر داده، که توسط مدیر داده در ارتباط با مدیر view اجرا می‌شوند، بر اساس مقدار پارامتر جدید به‌دست‌آمده از onQueryParamsDataUpdate() به‌روزرسانی می‌شوند.

بهره برداری از برنامه نویسی تابعی

فقط به این دلیل که هسته Oats~i از OOP استفاده می کند، به این معنی نیست که شما کاملاً محدود به ایجاد کتابخانه هایی هستید که از پارادایم OOP پیروی می کنند. به سادگی آگاه کردن آنها از چرخه زندگی کافی است.

این به آن‌ها اجازه می‌دهد تا منابع را به‌عنوان قطعه‌ای که Oats~i رندر می‌کند و از بین می‌برد، آزاد کنند.

هنگام انتقال مشتری Verte به Oats~i، من از این استراتژی دقیق برای استفاده مجدد از برخی از اسکریپت های کاربردی که برای صفحات وب اصلی نوشته بودم استفاده کرده ام.

بنابراین، من انتظار دارم که برای توسعه دهندگانی که به دنبال استفاده از اسکریپت های کاربردی خود در پروژه Oats~i هستند، تنگناها و سختگیری های پارادایم بسیار کمی داشته باشند، تا زمانی که از چرخه حیات آگاه باشند.

رندر سمت سرور (نماها و داده ها)

در نهایت، بخش بزرگی از چارچوب های وب مدرن – رندر سمت سرور.
Oats~i به طور بومی از رندر سمت سرور پشتیبانی می کند، بدون نیاز به اجرای جاوا اسکریپت بر روی سرور.

با استفاده از HTMLWebpackPlugin، می‌توانید نماهایی را که برای هر قطعه در برنامه Oats~i خود استفاده می‌کنید، در فایل‌های .html/.hbs خود استخراج کنید که می‌توانید زمانی که مشتری درخواست صفحه‌ای در بارگذاری جدید می‌کند، آن‌ها را برای مشتری ارسال کنید.

تنها مورد نیاز این است که ساختار نمای شما از سرور همان چیزی باشد که برنامه آن را ارائه می‌دهد.

توضیحات تصویر

اما هنوز کارمان تمام نشده است.

هیدراتاسیون مدیر داده

نماهایی که از سرور خود ارائه می دهید به احتمال زیاد وضعیتی از داده ها را نشان می دهند. Oats~i چگونه این موضوع را مدیریت می کند و از حالت رندر سمت سرور پیش می رود؟

شما در حالت ایده آل از مدیر داده برای مدیریت نماهای پویا یا مبتنی بر داده در برنامه Oats~i خود استفاده خواهید کرد. اکنون، با استفاده از آن، می‌توانید از هیدراتاسیون سمت سرور استفاده کنید که از یک اسکریپت رندر شده در تگ head از سرور استفاده می‌کند تا به مدیر داده کمک کند تا وضعیت داده‌ها را از سرور درک کند، آن را ذخیره کند، و مدیران نمای پیوستی را نیز به‌روزرسانی وضعیت‌های خود داشته باشد. بر اساس آن، و از آنجا به اجرای برنامه ادامه دهید.

در اینجا نحوه عملکرد آن آمده است.

در قسمت نشانه گذاری خود، در سرور، می توانید یک اسکریپت با فرمت زیر اضافه کنید:


وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این اسکریپت اطلاعات مهمی را برای مدیر داده از سرور فراهم می کند که تصویر کامل یا ایده ای از وضعیت داده را به آن می دهد.

هر مدیر داده یک “info_key” خواهد داشت که وضعیت داده خود را از آن می خواند. هنگامی که مدیر داده را تنظیم کردید تا از سمت سرور هیدراته شود، اسکریپت را با شناسه ای که ارائه می کنید پیدا می کند، متغیر در معرض نمایش داده شده DataManagerHydrationInfo را دریافت می کند و مقدار “info_key” را می خواند.

این مقدار باید یک آرایه باشد که در حالت ایده آل از همان نوع مدل مدیر داده است. با این حال، می تواند متفاوت باشد.

به این دلیل که مدیر داده یک فرآیند هیدراتاسیون چند مرحله ای را اجرا می کند.

اعتبار سنجی

خواندن از روی یک اسکریپت می تواند مشکلات و آسیب پذیری های خاص خود را داشته باشد. می توانید قبل از اینکه مدیر داده آن را انجام دهد، یک بررسی اعتبار سنجی روی داده های ذخیره شده در اسکریپت هیدراتاسیون انجام دهید.

پیش پردازش

بسته به منطق کسب و کار و طراحی برنامه وب شما، قالب داده ای که از سرور شما تهیه می شود می تواند با مدلی که در مدیریت داده خود اجرا می کنید متفاوت باشد. مدیر داده Oats~i یک مرحله پیش پردازش اختیاری را در طول هیدراتاسیون اجرا می کند که به شما امکان می دهد داده ها را از هیدراتور به فرمت مدل خود تبدیل کنید.

مرحله شبکه

این مرحله به شما این امکان را می‌دهد که در مورد داده‌هایی که در اسکریپت هیدراتاسیون خود آزاد می‌کنید، محتاط باشید، به روی اسکریپرهای وب، روبات‌ها و موتورهای جستجو باز است.

می‌توانید یک مرحله شبکه اختیاری را اجرا کنید که در آن می‌توانید داده‌های خصوصی یا پنهانی را که مدل مدیر داده‌تان به آن نیاز دارد، دریافت کنید، اما هرگز نباید از اسکراپرهای وب یا روبات‌هایی که وب را می‌شویند، مطلع باشید.

به عنوان مثال، اگر سبد خرید را هیدراته می‌کنید، می‌توانید اسکریپت هیدراتاسیون از سرور فقط حاوی اطلاعات کلی در مورد محصولات باشد، با شناسه‌های عمومی که وقتی به باطن امن شما منتقل می‌شوند، اطلاعات محرمانه بیشتری را که استفاده می‌کنید برمی‌گرداند. برای بررسی کاربر

بنابراین، اسکریپت هیدراتاسیون شما می‌تواند اطلاعاتی را به همان اندازه که قبلاً در html ارائه شده است، در خود نگه دارد، از مدیر داده بخواهید آن را بلافاصله به صورت داخلی انجام دهد، سپس همه چیزهای دیگر را از چرخه شبکه تهیه کنید.

بعدی برای Oats~i چیست؟

اگر تا این لحظه موفق به خواندن شده اید، آفرین، شما یک قهرمان هستید! این بهترین کاری است که می‌توانم انجام دهم تا تقریباً چهار سال کار را در یک پست وبلاگ کوچک «مقدمه‌ای» جمع کنم.

Oats~i یک پروژه یادگیری عظیم برای من بوده است و هم مضطرب و هم هیجان زده هستم تا جامعه فناوری را در مورد آن بدانند. چیزهای زیادی برای باز کردن، آموزش، یادگیری و اشکال زدایی وجود دارد.

برنامه من در حال حاضر این است که متن باز Oats~i. من روی جزئیات کار می‌کنم و امیدوارم در چند روز آینده کل پایگاه کد کاهش پیدا کند و همه ما بتوانیم در آن جستجو کنیم، برنامه‌های وب واقعی را از طریق چارچوب بسازیم، و سرعت آن را بالا ببریم.

در حال حاضر، من از بازخورد، نظرات، و سؤالات شما در مورد Oats~i، در صورت داشتن هرگونه، قدردانی خواهم کرد.
وب سایت Verte Environmental Solution را بررسی کنید و آن را در عمل ببینید.

من در لینکدین در دسترس هستم، پس بروید و سلام کنید.

به زودی می بینمت، زمانی که امیدواریم ساختن با Oats~i را شروع کنیم.

ویرایش: کد منبع اکنون عمومی است. https://github.com/Oats-i/Oats-i

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا