اشتراکها
در این سری قصد داریم یک برنامهی سادهی دفترچه تلفن را توسط Angular 6x و کامپوننتهای متریال آن ایجاد کنیم؛ اما Grid جزئی از بستهی Angular Material نیست. بنابراین برای طرحبندی برنامه و قرار دادن المانهای مختلف در مکانهای تعیین شدهی صفحه، از Angular FlexBox Module استفاده خواهیم کرد که محصور کنندهی CSS 3 FlexBox است.
آشنایی با Flex Layout Box Model
برای طراحی ظاهر یک برنامهی وب نیاز است عناصر آنرا در مکانهای مختلفی از صفحه قرار داد که به آن Layout گفته میشود. برای این منظور عموما 4 روش ذیل مرسوم هستند:
1. Table
2. Float, position, clear
3. CSS Grids
4. FlexBox CSS
امروزه دیگر آنچنان روشهای 1 و 2 به صورت مستقیم مورد استفاده قرار نمیگیرند. CSS Grid روش نهایی طراحی Layout در آینده خواهد بود و در حال حاضر تعداد مرورگرهایی که از آن پشتیبانی میکنند، قابل توجه نیست؛ اما از FlexBox در IE 11، کروم 21 و فایرفاکس 22 به بعد پشتیبانی میشود.
FlexBox CSS، سیلان المانهای قرار گرفتهی در داخل آنرا سبب میشود. در اینجا یک container اصلی وجود دارد که در برگیرندهی المانها است. در تصویر فوق دو محور را مشاهده میکنید. محور افقی از چپ به راست ادامه پیدا میکند. محور عمودی نحوهی ارتباط عناصر را مشخص میکند.
اکنون این سؤال مطرح میشود که چه تفاوتی بین یک Grid و FlexBox CSS وجود دارد؟ در یک Grid طراحی دو بعدی سطرها و ستون وجود دارد. اما به FlexBox باید به صورت سیلان یک بعدی سلولها نگاه کرد. برای مثال عناصر قرار گرفتهی درون Container یا به صورت افقی درون آن گسترده شده و قرار میگیرند و یا به صورت عمودی.
نحوهی تفکر و کارکرد با FlexBox چگونه است؟
در اینجا باید به دو مفهوم دقت داشت:
الف) سیلان عناصر درون Container که میتواند افقی و یا عمودی باشد.
ب) اندازهی المانها که میتواند ثابت و یا نسبی باشد.
یک Container، جهت سیلان عناصر درون آنرا مشخص میکند. المانهای آن، اندازه، فاصلهی از یکدیگر و ترتیب قرارگیری را ارائه میدهند. یک flex container میتواند شامل چندین flex container تو در تو نیز باشد.
نحوهی سیلان عناصر در FlexBox چگونه است؟
برای نمونه طرحبندی متداول ذیل را درنظر بگیرید:
نحوه تفکر در مورد طراحی این طرحبندی، باید از بیرون به درون و از بالا به پایین (سیلان عمودی) باشد:
سپس نحوهی سیلان عناصر درون Containerهای تعریف شده را مشخص میکنیم. برای مثال اولین Container دارای سیلان افقی از چپ به راست خواهد بود که عنصر سوم آن به دلیل اندازههای مشخص دو عنصر قبلی، به سطر دوم منتقل شدهاست.
در ادامه به قسمت میانی میرسیم که آن نیز دارای سیلان افقی از چپ به راست است:
در اینجا نیز میتوان سه Container را متصور شد که وسطی دارای سیلان افقی از راست به چپ است و مواردی که بر اساس اندازهی آنها در یک سطر جا نشدهاند، به سطر بعدی منتقل خواهند شد:
و تمام این سیلانها و انتقال به سطرهای بعدی بر اساس اندازهی المانها صورت میگیرد:
البته در این تصویر یک ایراد هم وجود دارد. با توجه به اینکه در ناحیهی میانی سه Container تعریف خواهند شد. Container ایی که در میان آن قرار میگیرد، دارای سیلان خاص خودش است و اندازههای آن باید نسبت به این Container تعریف شوند و نه نسبت به کل ناحیهی میانی. یعنی بجای اینکه 50 درصد، 25، 25 و 50 درصد را داشته باشیم، اینها در اصل 100 درصد، 50 و 50 درصد و سپس 100 درصد هستند.
معرفی کتابخانهی Angular Flex Layout
برای کار با Flex CSS نیاز است:
- مقدار زیادی کد CSS نوشت.
- نیاز به درک عمیقی از Flex Box دارد.
- نیاز است با باگهای مرورگرها و تفاوتهای پیاده سازیهای آنها در مورد FlexBox آشنا بود.
- نیاز به Prefixing دارد.
- برای Angular طراحی نشدهاست.
جهت رفع این مشکلات و محدودیتها، تیم Angular کتابخانهای را به نام Angular Flex Layout مخصوص نگارشهای جدید Angular طراحی کردهاست. این کتابخانه مستقل از Angular Material است اما عموما به همراه آن استفاده میشود.
مزایای کار با کتابخانهی Angular flex layout
- پیاده سازی TypeScript ایی دارد. در اصل یک سری directives مخصوص Angular است که با TypeScript نوشته شدهاست.
- به صورت پویا و inline تمام CSSهای مورد نیاز را تولید و تزریق میکند.
- به همراه یک API استاتیک است و همچنین یک API واکنشگرا
- با Angular CLI نیز یکپارچه شدهاست.
نصب و تنظیم کتابخانهی Angular Flex layout
برای نصب این کتابخانه، در ریشهی پروژه دستور زیر را صادر کنید:
سپس ماژول آنرا باید به shared.module.ts اضافه کرد:
کار با API استاتیک Angular Flex layout
API استاتیک Angular Flex layout شامل این مزایا و مشخصات است:
- به صورت یکسری دایرکتیو Angular طراحی شدهاست که به HTML قالب کامپوننتها اضافه میشود.
- از data binding پشتیبانی میکند.
- CSS نهایی را به صورت پویا و inline تولید و به صفحه تزریق میکند. Inline CSS تزریق شده به ویژگیهای styles هر المان تزریق میشوند و موارد مشابه را در صورت وجود بازنویسی میکنند.
- از تشخیص تغییرات پشتیبانی میکند.
- به همراه ویژگیهای fxHide و fxShow است.
- کارآیی مطلوبی دارد.
در اینجا برای تعریف container اصلی از دایرکتیوهای زیر استفاده میشود:
- fxLayout جهتهای flex را مشخص میکند.
- fxLayout میتواند دارای مقداری مانند row، column و row-reverse و column-reverse باشد. برای مثال مقدار row-reverse، نمایش از راست به چپ را سبب میشود.
- fxLayoutWrap مشخص میکند که آیا المانها باید به سطر و یا ستون بعدی منتقل شوند یا خیر؟
- fxLayoutGap فاصلهی بین المانها را مشخص میکند.
- fxLayoutAlign نحوهی چیدمان المان را تعیین میکند.
چند مثال:
و یا حالت راست به چپ آن به صورت زیر است:
و برای تعریف آیتمهای قرار گرفتهی درون containers میتوان از دایرکتیوهای زیر استفاده کرد:
- fxflex برای تعیین اندازه و flex المانها
در اینجا سه مقداری که ذکر میشوند (و یا تنها یک مقدار) چنین معنایی را به همراه دارند:
و یا
- grow به این معنا است که آیتم جاری در صورت وجود فضا (طراحی واکنشگرا و واکنش نشان دادن به اندازهی صفحه)، نسبت به سایر المانها تا چه اندازهای میتواند بزرگ شود.
- shrink به این معنا است که اگر به اندازهی کافی فضا وجود نداشت، این المان نسبت به سایر المانهای دیگر تا چه اندازهای میتواند کوچک شود.
- basis به معنای اندازهی پیشفرض المان است.
در اینجا اندازهها برحسب پیکسل، درصد و یا calcs, em, cw, vh میتوانند تعیین شوند. همچنین یک سری نام مستعار مانند grow, initial, auto, none, nogrow, noshrink هم قابل استفاده هستند.
- fxflexorder برای تعیین ترتیب قرارگیری یک المان
- fxflexoffset برای تعیین فاصله یک المان از container آن
- fxflexAlign برای تعیین محل قرارگیری المان
- fxflexfill برای تعیین اینکه این المان کل ردیف یا ستون را پر خواهد کرد
چند مثال:
در اینجا سه نمایشی را که در ذیل تعریف divها مشاهده میکنید بر اساس تغییر اندازهی صفحه حاصل شدهاند. چون آیتم دوم دارای مقدار grow مساوی 5 است، به همین جهت با تغییر اندازهی صفحه و دسترسی به مقدار فضای بیشتر، بزرگتر شدهاست.
یک مثال کامل
اگر علاقمند باشید تا توانمندیهای angular flex layout را در قالب یک مثال کامل مشاهده کنید، به آدرس زیر مراجعه نمائید:
https://tburleson-layouts-demos.firebaseapp.com/#/docs
در این مثال با تغییر گزینههای مختلف، کد معادل angular flex layout آن نیز تولید میشود.
همچنین wiki خود پروژه نیز به همراه مثالهای بیشتری است:
https://github.com/angular/flex-layout/wiki
کار با API واکنشگرای Angular Flex layout
در طراحی واکنشگرا، container و عناصر داخل آن بر اساس تغییرات اندازهی صفحه و یا اندازهی وسیلهی نمایشی، تغییر اندازه و همچنین موقعیت میدهند و این تغییرات بر اساس انطباق با viewport وسیلهی نمایشی صورت میگیرند. به همین جهت برای طراحی واکنشگرا نیاز به Flex CSS و همچنین Media Query است. نوشتن Medial Query و ترکیب آن با Flex CSS کار مشکلی است. به همین جهت Angular Flex layout به همراه یک API واکنشگرا نیز هست که در پشت صحنه Flex CSS را بر اساس طراحی متریال و Medial Queries مورد استفاده قرار میدهد.
اگر علاقمند هستید تا اندازههای واکنشگرای استاندارد متریال را ملاحظه کنید، میتوانید به آدرس زیر مراجعه نمائید (قسمت Breakpoint system آن):
https://material.io/design/layout/responsive-layout-grid.html#breakpoints
برای مثال هر اندازهای کمتر از 600px در گروه extra small قرار میگیرد (با مخفف xs). از 600px تا 1024px در بازهی small (با مخفف sm)، از 1024px تا 1440px در بازهی medium (با مخفف md) و از 1440px تا 1920px در بازهی large (با مخفف lg) و بیشتر از آن در بازهی xlrage قرار میگیرند (با مخفف xl). این اعداد و بازهها، پایهی طراحی API واکنشگرای Angular Flex layout هستند. به همین جهت نام این بازهها در این API به صورت مخفف xs, sm, md, lg, xl درنظر گرفته شدهاند و مورد استفاده قرار میگیرند. همچنین اگر اندازههای مدنظر از این بازهها کمتر باشند، میتوان از lt-sm, lt-md, lt-lg, lt-xl نیز استفاده کرد. در اینجا lt به معنای less than است و یا اگر بازههای مورد نیاز بیش از این اندازهها باشند میتوان با gt-xs, gt-sm, gt-md, gt-lg کار کرد. در اینجا gt به معنای greater than است.
به این مخففها «media query alias» هم گفته میشود و اکنون که لیست آنها مشخص است، تنها کافی است آنها را به API استاتیکی که پیشتر بررسی کردیم، اضافه کنیم. برای مثال:
برای نمونه فرض کنید یک چنین طرحبندی دسکتاپی را داریم:
معادل طراحی آن با API استاتیک Angular Flex Layout به صورت زیر است:
اکنون که این طرحبندی دسکتاپ را داریم، چگونه باید آنرا تبدیل به طرحبندی موبایل، مانند شکل زیر کنیم؟
برای اینکار ابتدا fxLayout.xs را به سطر میانی اضافه میکنیم تا هرگاه به این اندازه رسیدیم، بجای ردیف، تبدیل به ستون شود. سپس توسط fxFlexOrder.xs، در اندازهی xs، محل قرارگیری المانهای این ستون را هم مشخص میکنیم:
همانطور که ملاحظه میکنید کار کردن با این API بسیار سادهاست و نیازی به کارکردن مستقیم با Media Queries و یا برنامه نویسی مستقیم ندارد و تمام آن در قالب HTML یک کامپوننت قابل پیاده سازی است.
یک نکته: مثال کاملی که پیشتر در این بحث مطرح شد، به همراه مثال واکنشگرا نیز هست که برای مشاهدهی اثر آنها بهتر است اندازهی مرورگر را کوچک و بزرگ کنید.
مخفی کردن و یا نمایش قسمتی از صفحه بر اساس اندازهی آن
علاوه بر media query alias هایی که عنوان شد، امکان نمایش و یا مخفی سازی قسمتهای مختلف صفحه بر اساس اندازهی صفحهی نمایشی نیز هست:
در اینجا fxShow سبب نمایش این div در حالت عادی میشود (پیشفرض آن xl، md و sm است). اما اگر اندازهی صفحه lg باشد، fxHide.lg تنظیم شدهی به true سبب مخفی سازی آن خواهد شد و در اندازهی xs مجددا نمایش داده میشود.
تغییر اندازهی قسمتی از صفحه بر اساس اندازهی آن
در مثال زیر اگر اندازهی صفحه gt-sm باشد (بیشتر از small)، اندازهی این div به 100 درصد بجای 50 درصد حالتهای دیگر، تنظیم میشود:
حالتهای ویژهی طراحی واکنشگرا در Angular Flex Layout
در API واکنشگرای آن حالتهای ویژهی fxshow, fxhide, ngclass و ngstyle نیز درنظر گرفته شدهاند که امکان فعالسازی آنها در اندازههای مختلف صفحه مسیر است:
امکان کار با API واکنشگرا از طریق برنامه نویسی
برای این منظور میتوان از سرویس ObservableMedia مانند مثال زیر استفاده کرد:
در اینجا به فعالسازی یک بازهی خاص گوش فرا خواهیم داد. برای مثال اگر اندازهی صفحه xs بود، سبب بارگذاری محتوای خاص مرتبط با موبایل خواهیم شد.
برای مطالعهی بیشتر
آشنایی با Flex Layout Box Model
برای طراحی ظاهر یک برنامهی وب نیاز است عناصر آنرا در مکانهای مختلفی از صفحه قرار داد که به آن Layout گفته میشود. برای این منظور عموما 4 روش ذیل مرسوم هستند:
1. Table
2. Float, position, clear
3. CSS Grids
4. FlexBox CSS
امروزه دیگر آنچنان روشهای 1 و 2 به صورت مستقیم مورد استفاده قرار نمیگیرند. CSS Grid روش نهایی طراحی Layout در آینده خواهد بود و در حال حاضر تعداد مرورگرهایی که از آن پشتیبانی میکنند، قابل توجه نیست؛ اما از FlexBox در IE 11، کروم 21 و فایرفاکس 22 به بعد پشتیبانی میشود.
FlexBox CSS، سیلان المانهای قرار گرفتهی در داخل آنرا سبب میشود. در اینجا یک container اصلی وجود دارد که در برگیرندهی المانها است. در تصویر فوق دو محور را مشاهده میکنید. محور افقی از چپ به راست ادامه پیدا میکند. محور عمودی نحوهی ارتباط عناصر را مشخص میکند.
اکنون این سؤال مطرح میشود که چه تفاوتی بین یک Grid و FlexBox CSS وجود دارد؟ در یک Grid طراحی دو بعدی سطرها و ستون وجود دارد. اما به FlexBox باید به صورت سیلان یک بعدی سلولها نگاه کرد. برای مثال عناصر قرار گرفتهی درون Container یا به صورت افقی درون آن گسترده شده و قرار میگیرند و یا به صورت عمودی.
نحوهی تفکر و کارکرد با FlexBox چگونه است؟
در اینجا باید به دو مفهوم دقت داشت:
الف) سیلان عناصر درون Container که میتواند افقی و یا عمودی باشد.
ب) اندازهی المانها که میتواند ثابت و یا نسبی باشد.
یک Container، جهت سیلان عناصر درون آنرا مشخص میکند. المانهای آن، اندازه، فاصلهی از یکدیگر و ترتیب قرارگیری را ارائه میدهند. یک flex container میتواند شامل چندین flex container تو در تو نیز باشد.
نحوهی سیلان عناصر در FlexBox چگونه است؟
برای نمونه طرحبندی متداول ذیل را درنظر بگیرید:
نحوه تفکر در مورد طراحی این طرحبندی، باید از بیرون به درون و از بالا به پایین (سیلان عمودی) باشد:
سپس نحوهی سیلان عناصر درون Containerهای تعریف شده را مشخص میکنیم. برای مثال اولین Container دارای سیلان افقی از چپ به راست خواهد بود که عنصر سوم آن به دلیل اندازههای مشخص دو عنصر قبلی، به سطر دوم منتقل شدهاست.
در ادامه به قسمت میانی میرسیم که آن نیز دارای سیلان افقی از چپ به راست است:
در اینجا نیز میتوان سه Container را متصور شد که وسطی دارای سیلان افقی از راست به چپ است و مواردی که بر اساس اندازهی آنها در یک سطر جا نشدهاند، به سطر بعدی منتقل خواهند شد:
و تمام این سیلانها و انتقال به سطرهای بعدی بر اساس اندازهی المانها صورت میگیرد:
البته در این تصویر یک ایراد هم وجود دارد. با توجه به اینکه در ناحیهی میانی سه Container تعریف خواهند شد. Container ایی که در میان آن قرار میگیرد، دارای سیلان خاص خودش است و اندازههای آن باید نسبت به این Container تعریف شوند و نه نسبت به کل ناحیهی میانی. یعنی بجای اینکه 50 درصد، 25، 25 و 50 درصد را داشته باشیم، اینها در اصل 100 درصد، 50 و 50 درصد و سپس 100 درصد هستند.
معرفی کتابخانهی Angular Flex Layout
برای کار با Flex CSS نیاز است:
- مقدار زیادی کد CSS نوشت.
- نیاز به درک عمیقی از Flex Box دارد.
- نیاز است با باگهای مرورگرها و تفاوتهای پیاده سازیهای آنها در مورد FlexBox آشنا بود.
- نیاز به Prefixing دارد.
- برای Angular طراحی نشدهاست.
جهت رفع این مشکلات و محدودیتها، تیم Angular کتابخانهای را به نام Angular Flex Layout مخصوص نگارشهای جدید Angular طراحی کردهاست. این کتابخانه مستقل از Angular Material است اما عموما به همراه آن استفاده میشود.
مزایای کار با کتابخانهی Angular flex layout
- یک کتابخانهی متکی به خود و مستقل است و برای کار با آن الزامی به استفادهی از Angular Material نیست.
- به همراه هیچ فایل CSS جانبی ارائه نمیشود.- پیاده سازی TypeScript ایی دارد. در اصل یک سری directives مخصوص Angular است که با TypeScript نوشته شدهاست.
- به صورت پویا و inline تمام CSSهای مورد نیاز را تولید و تزریق میکند.
- به همراه یک API استاتیک است و همچنین یک API واکنشگرا
- با Angular CLI نیز یکپارچه شدهاست.
نصب و تنظیم کتابخانهی Angular Flex layout
برای نصب این کتابخانه، در ریشهی پروژه دستور زیر را صادر کنید:
npm install @angular/flex-layout --save
import { FlexLayoutModule } from "@angular/flex-layout"; @NgModule({ imports: [ FlexLayoutModule ], exports: [ FlexLayoutModule ] }) export class SharedModule { }
کار با API استاتیک Angular Flex layout
API استاتیک Angular Flex layout شامل این مزایا و مشخصات است:
- به صورت یکسری دایرکتیو Angular طراحی شدهاست که به HTML قالب کامپوننتها اضافه میشود.
- از data binding پشتیبانی میکند.
- CSS نهایی را به صورت پویا و inline تولید و به صفحه تزریق میکند. Inline CSS تزریق شده به ویژگیهای styles هر المان تزریق میشوند و موارد مشابه را در صورت وجود بازنویسی میکنند.
- از تشخیص تغییرات پشتیبانی میکند.
- به همراه ویژگیهای fxHide و fxShow است.
- کارآیی مطلوبی دارد.
در اینجا برای تعریف container اصلی از دایرکتیوهای زیر استفاده میشود:
- fxLayout جهتهای flex را مشخص میکند.
<div fxLayout="row" fxLayout.xs="column"></div>
- fxLayoutWrap مشخص میکند که آیا المانها باید به سطر و یا ستون بعدی منتقل شوند یا خیر؟
<div fxLayoutWrap></div>
<div fxLayoutGap="10px"></div>
<div fxLayoutAlign="start stretch"></div>
چند مثال:
و یا حالت راست به چپ آن به صورت زیر است:
و برای تعریف آیتمهای قرار گرفتهی درون containers میتوان از دایرکتیوهای زیر استفاده کرد:
- fxflex برای تعیین اندازه و flex المانها
<div fxFlex="1 2 calc(15em + 20px)"></div>
fxFlex="grow shrink basis"
fxFlex="basis"
- shrink به این معنا است که اگر به اندازهی کافی فضا وجود نداشت، این المان نسبت به سایر المانهای دیگر تا چه اندازهای میتواند کوچک شود.
- basis به معنای اندازهی پیشفرض المان است.
در اینجا اندازهها برحسب پیکسل، درصد و یا calcs, em, cw, vh میتوانند تعیین شوند. همچنین یک سری نام مستعار مانند grow, initial, auto, none, nogrow, noshrink هم قابل استفاده هستند.
- fxflexorder برای تعیین ترتیب قرارگیری یک المان
<div fxFlexOrder="2"></div>
<div fxFlexOffset="20px"></div>
<div fxFlexAlign="center"></div>
<div fxFlexFill></div>
چند مثال:
در اینجا سه نمایشی را که در ذیل تعریف divها مشاهده میکنید بر اساس تغییر اندازهی صفحه حاصل شدهاند. چون آیتم دوم دارای مقدار grow مساوی 5 است، به همین جهت با تغییر اندازهی صفحه و دسترسی به مقدار فضای بیشتر، بزرگتر شدهاست.
یک مثال کامل
اگر علاقمند باشید تا توانمندیهای angular flex layout را در قالب یک مثال کامل مشاهده کنید، به آدرس زیر مراجعه نمائید:
https://tburleson-layouts-demos.firebaseapp.com/#/docs
در این مثال با تغییر گزینههای مختلف، کد معادل angular flex layout آن نیز تولید میشود.
همچنین wiki خود پروژه نیز به همراه مثالهای بیشتری است:
https://github.com/angular/flex-layout/wiki
کار با API واکنشگرای Angular Flex layout
در طراحی واکنشگرا، container و عناصر داخل آن بر اساس تغییرات اندازهی صفحه و یا اندازهی وسیلهی نمایشی، تغییر اندازه و همچنین موقعیت میدهند و این تغییرات بر اساس انطباق با viewport وسیلهی نمایشی صورت میگیرند. به همین جهت برای طراحی واکنشگرا نیاز به Flex CSS و همچنین Media Query است. نوشتن Medial Query و ترکیب آن با Flex CSS کار مشکلی است. به همین جهت Angular Flex layout به همراه یک API واکنشگرا نیز هست که در پشت صحنه Flex CSS را بر اساس طراحی متریال و Medial Queries مورد استفاده قرار میدهد.
اگر علاقمند هستید تا اندازههای واکنشگرای استاندارد متریال را ملاحظه کنید، میتوانید به آدرس زیر مراجعه نمائید (قسمت Breakpoint system آن):
https://material.io/design/layout/responsive-layout-grid.html#breakpoints
برای مثال هر اندازهای کمتر از 600px در گروه extra small قرار میگیرد (با مخفف xs). از 600px تا 1024px در بازهی small (با مخفف sm)، از 1024px تا 1440px در بازهی medium (با مخفف md) و از 1440px تا 1920px در بازهی large (با مخفف lg) و بیشتر از آن در بازهی xlrage قرار میگیرند (با مخفف xl). این اعداد و بازهها، پایهی طراحی API واکنشگرای Angular Flex layout هستند. به همین جهت نام این بازهها در این API به صورت مخفف xs, sm, md, lg, xl درنظر گرفته شدهاند و مورد استفاده قرار میگیرند. همچنین اگر اندازههای مدنظر از این بازهها کمتر باشند، میتوان از lt-sm, lt-md, lt-lg, lt-xl نیز استفاده کرد. در اینجا lt به معنای less than است و یا اگر بازههای مورد نیاز بیش از این اندازهها باشند میتوان با gt-xs, gt-sm, gt-md, gt-lg کار کرد. در اینجا gt به معنای greater than است.
به این مخففها «media query alias» هم گفته میشود و اکنون که لیست آنها مشخص است، تنها کافی است آنها را به API استاتیکی که پیشتر بررسی کردیم، اضافه کنیم. برای مثال:
fxLayout.sm = "..." fxLayoutAlign.md = "..." fxHide.gt-sm = "..."
معادل طراحی آن با API استاتیک Angular Flex Layout به صورت زیر است:
که در اینجا دو container را ملاحظه میکنید. ابتدا Container بیرونی جهت ارائهی ستونی از سه المان اضافه شدهاست. سپس یک Container میانی برای تعریف ردیفی از سه المان تعریف شدهاست. توسط روش "fxFlex="grow shrink basis نیز اندازههای آنها مشخص شدهاند.
اکنون که این طرحبندی دسکتاپ را داریم، چگونه باید آنرا تبدیل به طرحبندی موبایل، مانند شکل زیر کنیم؟
برای اینکار ابتدا fxLayout.xs را به سطر میانی اضافه میکنیم تا هرگاه به این اندازه رسیدیم، بجای ردیف، تبدیل به ستون شود. سپس توسط fxFlexOrder.xs، در اندازهی xs، محل قرارگیری المانهای این ستون را هم مشخص میکنیم:
همانطور که ملاحظه میکنید کار کردن با این API بسیار سادهاست و نیازی به کارکردن مستقیم با Media Queries و یا برنامه نویسی مستقیم ندارد و تمام آن در قالب HTML یک کامپوننت قابل پیاده سازی است.
یک نکته: مثال کاملی که پیشتر در این بحث مطرح شد، به همراه مثال واکنشگرا نیز هست که برای مشاهدهی اثر آنها بهتر است اندازهی مرورگر را کوچک و بزرگ کنید.
مخفی کردن و یا نمایش قسمتی از صفحه بر اساس اندازهی آن
علاوه بر media query alias هایی که عنوان شد، امکان نمایش و یا مخفی سازی قسمتهای مختلف صفحه بر اساس اندازهی صفحهی نمایشی نیز هست:
<div fxShow fxHide.xs="false" fxHide.lg="true"></div>
تغییر اندازهی قسمتی از صفحه بر اساس اندازهی آن
در مثال زیر اگر اندازهی صفحه gt-sm باشد (بیشتر از small)، اندازهی این div به 100 درصد بجای 50 درصد حالتهای دیگر، تنظیم میشود:
<div fxFlex="50%" fxFlex.gt-sm="100%"></div>
حالتهای ویژهی طراحی واکنشگرا در Angular Flex Layout
در API واکنشگرای آن حالتهای ویژهی fxshow, fxhide, ngclass و ngstyle نیز درنظر گرفته شدهاند که امکان فعالسازی آنها در اندازههای مختلف صفحه مسیر است:
<div fxShow [fxShow.xs]="isVisibleOnMobile()"></div> <div fxHide [fxHide.gt-sm]="isVisibleOnDesktop()"></div> <div [ngClass.sm]="{'fxClass-sm': hasStyle}" ></div> <div [ngStyle.xs]="{color: 'blue'}"></div>
امکان کار با API واکنشگرا از طریق برنامه نویسی
برای این منظور میتوان از سرویس ObservableMedia مانند مثال زیر استفاده کرد:
در اینجا به فعالسازی یک بازهی خاص گوش فرا خواهیم داد. برای مثال اگر اندازهی صفحه xs بود، سبب بارگذاری محتوای خاص مرتبط با موبایل خواهیم شد.
برای مطالعهی بیشتر
قسمتهای عمدهای از مطلب جاری، از ویدیوی زیر که توسط نویسندهی اصلی angular flex layout تهیه شدهاست، گردآوری شدند.
عصر Thick Clients
امن سازی برنامههای وب همواره چالش برانگیز بودهاست؛ خصوصا این روزها که نیاز است برنامهها، خارج از دیوارهای یک شرکت نیز در دسترس باشند و توسط انواع و اقسام وسایل ارتباطی مورد استفاده قرار گیرند. در سالهای قبل، عموما برنامههای thick clients مانند WPF و WinForms برای شرکتها توسعه داده میشدند و یا برنامههای وب مانند ASP.NET Web Forms که مبتنی بر سرویسها نبودند. در برنامههای ویندوزی، پس از لاگین شخص به شبکه و دومین داخلی شرکت، عموما از روش Windows Authentication برای مشخص سازی سطوح دسترسی کاربران استفاده میشود. در برنامههای Web Forms نیز بیشتر روش Forms Authentication برای اعتبارسنجی کاربران مرسوم است. امن سازی این نوع برنامهها سادهاست. عموما بر روی یک دومین ارائه میشوند و کوکیهای اعتبارسنجی کاربران برای ارائهی مباحثی مانند single sign-on (داشتن تنها یک صفحهی لاگین برای دسترسی به تمام برنامههای شرکت)، میسر است.
عصر شروع بهکارگیری سرویسهای وب
در سالهای اخیر این شیوهی کاری تغییر کرده و بیشتر بر اساس بکارگیری برنامههای مبتنی بر سرویسها شدهاست. برای مثال برای این مورد استاندارد WS-Security مربوط به WCF ارائه شدهاست که باز هم مرتبط است به برنامههای یک دومین و یا یک Application pool. اگر تعداد دومینها بیشتر شوند و نیاز به ارتباط امن بین آنها باشد، استاندارد SAML 2.0 مورد استفاده قرار میگرفت که هدف از آن، انتقال امن اعتبارسنجی و سطوح دسترسی کاربران بین دومینهای مختلف است. همانطور که ملاحظه میکنید تمام این برنامهها و استانداردها، داخل دیوارهای یک شرکت و یک دومین زندگی میکنند.
عصر شروع بهکارگیری Restful-API's
پس از آن باز هم شیوهی طراحی برنامههای تغییر کرد و شروع به ایجاد Restful-API's و HTTP API's کردیم. اینها دیگر الزاما داخل یک دومین ارائه نمیشوند و گاهی از اوقات حتی تحت کنترل ما هم نیستند. همچنین برنامههای ارائه شده نیز دیگر thick clients نیستند و ممکن است برنامههای سمت کلاینت Angular و یا حتی موبایل باشند که مستقیما با سرویسهای API برنامهها کار میکنند. حتی ممکن است یک API را طراحی کنیم که با یک API دیگر کار میکند.
در این حالت دیگر نمیتوان این APIها را با نگهداری آنها داخل دیوارهای یک شرکت محافظت کرد. اگر قرار است با یک HTTP API کار کنیم، این API باید عمومی باشد و در اینجا دیگر نمیتوان از روش Forms Authentication استفاده کرد. زیرا این روش اعتبارسنجی مختص برنامههای سمت سرور قرار گرفتهی در یک دومین طراحی شدهاست و آنچنان سازگاری با برنامههای سمت کلاینت و موبایل خارج از دیوارهای آن ندارد. همچنین ارسال نام کاربری و کلمهی عبور به ازای هر درخواست نیز روشی بسیار بدوی و نا امن است. اینجا است که عصر امن سازی برنامهها به کمک توکنها شروع میشود. با استفادهی از توکنها، بجای هر بار ارسال نام کاربری و کلمهی عبور به ازای هر درخواست از API، صرفا لیست سطوح دسترسی امضا شدهی به امکاناتی خاص، ارسال میشوند.
عصر شروع بهکارگیری Security Tokens
بنابراین در اینجا نیاز به برنامهای برای تولید توکنها و ارسال آنها به کلاینتها داریم. روش متداول پیاده سازی آن، ساخت یک برنامهی ابتدایی، برای دریافت نام کاربری و کلمهی عبور از کاربران و سپس بازگشت یک JSON Web Token به آنها است که بیانگر سطوح دسترسی آنها به قسمتهای مختلف برنامه است و کاربران باید این توکن را به ازای هر درخواستی به سمت سرور (بجای نام کاربری و کلمهی عبور و خود) ارسال کنند.
مشکل این روش در اینجا است که آن برنامهی خاص، باید از نام کاربری و کلمهی عبور کاربران مطلع باشد تا بتواند توکن مناسبی را برای آن کاربر خاص تولید کند. هر چند این روش برای یک تک برنامهی خاص بسیار مناسب به نظر میرسد، اما در یک شرکت، دهها برنامه مشغول به کارند و به اشتراک گذاری نام کاربری و کلمهی عبور کاربران، با تک تک آنها ایدهی مناسبی نیست و پس از مدتی از کنترل خارج خواهد شد. برای مثال کاربری در یک برنامه، کلمهی عبور خود را تغییر میدهد اما در برنامهای دیگر خیر و همین مسالهی عدم هماهنگی بین برنامهها و همچنین بخشهای مختلف یک شرکت، مدیریت یک دست برنامهها را تقریبا غیر ممکن میکند. همچنین در اینجا برنامههای ثالث را نیز باید در نظر داشت که آیا ضروری است آنها به ریز اطلاعات کاربران شرکت دسترسی پیدا کنند؟
به علاوه مشکل دیگر توسعهی این نوع برنامههای صدور توکن خانگی، اختراع مجدد چرخ است. در اینجا برای بهبود امنیت برنامه باید منقضی شدن، تمدید، امضای دیجیتال و اعتبارسنجی توکنها را خودمان پیاده سازی کنیم. توسعهی یک چنین سیستمی اگر غیرممکن نباشد، بسیار سخت و پیچیده است و همچنین باید باگهای امنیتی ممکن را نیز مدنظر داشت.
بنابراین تا اینجا به این نتیجه رسیدهایم که دیگر نمیخواهیم مدیریت نام کاربری و کلمهی عبور کاربران را در سطح هیچکدام از برنامههای خود انجام دهیم و هیچکدام از آنها قرار نیست دریافت کنندهی این اطلاعات باشند. قرار است این کار، به یک تک برنامهی مرکزی مخصوص اینکار منتقل شود و برای اینکار نیاز به پروتکلی امن است که بتوان این توکنهای تولیدی را ارسال و پردازش کرد.
حرکت به سمت «تامین کنندهی هویت مرکزی»
در گذشته، هر تک برنامهای دارای صفحهی لاگین و امکانات مدیریت کاربران آن، تغییر کلمهی عبور، تنظیم مجدد آن و اینگونه عملیات بود. اینروزها دیگر چنین کاری مرسوم نیست. این وظیفهی برنامهی شما نیست که بررسی کند کاربر وارد شدهی به سیستم کیست و آیا ادعای او صحیح است یا خیر؟ این نوع عملیات وظیفهی یک Identity provider و یا به اختصار IDP است. کار IDP اعتبارسنجی کاربر و در صورت نیاز، ارائهی اثبات هویت کاربر، به برنامهی درخواست کنندهاست.
در یک IDP عملیاتی مانند ثبت کاربران و مدیریت آنها انجام میشود. اینجا است که مفاهیمی مانند قفل کردن اکانت و یا تغییر کلمهی عبور و امثال آن انجام میشود و نه اینکه به ازای هر برنامهی تهیه شدهی برای یک شرکت، آن برنامه راسا اقدام به انجام چنین عملیاتی کند. به این ترتیب میتوان به امکان استفادهی مجدد از اطلاعات هویت کاربران و سطوح دسترسی آنها در بین تمام برنامههای موجود رسید.
همچنین با داشتن یک برنامهی IDP خوب پیاده سازی شده، از توزیع باگهای امنیتی مختلف در بین برنامههای گوناگون تهیه شده که هر کدام سیستم امنیتی خاص خودشان را دارند، جلوگیری خواهد شد. برای مثال فرض کنید میخواهید الگوریتم هش کردن پسوردهای سیستم را که امروز نا امن اعلام شدهاست، تغییر دهید. با داشتن یک IDP، دیگر نیازی نیست تا تمام برنامههای خود را برای رفع یک چنین باگهایی، تک تک تغییر دهید.
به علاوه این روزها روش استفادهی از نام کاربری و کلمهی عبور، تنها راه ورود به یک سیستم نیست و استفاده از کلیدهای دیجیتال و یا روشهای ویژهی ابزارهای موبایل نیز به این لیست اضافه شدهاند.
حرکت به سمت استاندارد OAuth 2
OAuth 2.0 پروتکلی است استاندارد، برای Authorization امن کاربران، توسط برنامههای وب، موبایل و دسکتاپ. به این ترتیب میتوان امکان دسترسی یک برنامه را به یک API، به نحوی استاندارد و امن میسر ساخت. OAuth 2.0 یک توکن دسترسی (Access token) را تولید میکند و در اختیار کلاینت قرار میدهد. سپس آن کلاینت با ارسال این توکن به API مدنظر، امکان دسترسی به امکانات مختلف آنرا خواهد یافت. به علاوه چون ماهیت برنامههای کلاینت وب و غیر وب متفاوت است، این استاندارد نحوهی دریافت چنین توکنی را برای برنامههای مختلف نیز تعریف میکند. به این ترتیب موارد مشترکی مانند تولید و نحوهی انتقال توکنها به کلاینتهای مختلف توسط این پروتکل استاندارد بیان میشود. در این حالت راهحلهای خانگی ما تبدیل به راهحلهایی میشوند که استاندارد OAuth 2.0 را پیاده سازی کرده باشند. بنابراین IDP ما باید بر مبنای این استاندارد تهیه شده باشد. برای مثال IdentityServer که در این سری بررسی خواهد شد و یا Azure Active Directory، نمونهای از IDPهایی هستند که این استاندارد را کاملا پیاده سازی کردهاند.
البته باید دقت داشت که این توکنهای دسترسی، تنها سطوح دسترسی به منابع API را مشخص میکنند و یا به عبارتی عملیات Authorization توسط آنها میسر میشود. عملیات ورود به سیستم اصطلاحا Authentication نام دارد و توسط استاندارد دیگری به نام OpenID Connect مدیریت میشود.
حرکت به سمت استاندارد OpenID Connect
OpenID Connect یک لایهی امنیتی بر فراز پروتکل OAuth 2.0 است که به اختصار به آن OIDC نیز گفته میشود. توسط آن یک کلاینت میتواند یک Identity token را علاوه بر Access token درخواست کند. از این Identity token برای ورود به برنامهی کلاینت استفاده میشود (Authentication) و پس از آن، برنامهی کلاینت بر اساس سطوح دسترسی تعریف شدهی در Access token، امکان دسترسی به امکانات مختلف یک API را خواهد یافت (Authorization). همچنین OpenID Connect امکان دسترسی به اطلاعات بیشتری از یک کاربر را نیز میسر میکند.
بنابراین OpenID Connect پروتکلی است که در عمل استفاده میشود و توسعه دهنده و جایگزین کنندهی پروتکل OAuth 2.0 میباشد. هرچند ممکن است در بسیاری از منابع صرفا به OAuth 2.0 بپردازند، اما در پشت صحنه با همان OpenID Connect کار میکنند.
مزیت دیگر کار با OpenID Connect، عدم الزام به استفادهی از API، در برنامهای خاص و یا قدیمی است. اگر برنامهی وب شما با هیچ نوع API ایی کار نمیکند، باز هم میتوانید از امکانات OpenID Connect بهرهمند شوید.
امن سازی برنامههای وب همواره چالش برانگیز بودهاست؛ خصوصا این روزها که نیاز است برنامهها، خارج از دیوارهای یک شرکت نیز در دسترس باشند و توسط انواع و اقسام وسایل ارتباطی مورد استفاده قرار گیرند. در سالهای قبل، عموما برنامههای thick clients مانند WPF و WinForms برای شرکتها توسعه داده میشدند و یا برنامههای وب مانند ASP.NET Web Forms که مبتنی بر سرویسها نبودند. در برنامههای ویندوزی، پس از لاگین شخص به شبکه و دومین داخلی شرکت، عموما از روش Windows Authentication برای مشخص سازی سطوح دسترسی کاربران استفاده میشود. در برنامههای Web Forms نیز بیشتر روش Forms Authentication برای اعتبارسنجی کاربران مرسوم است. امن سازی این نوع برنامهها سادهاست. عموما بر روی یک دومین ارائه میشوند و کوکیهای اعتبارسنجی کاربران برای ارائهی مباحثی مانند single sign-on (داشتن تنها یک صفحهی لاگین برای دسترسی به تمام برنامههای شرکت)، میسر است.
عصر شروع بهکارگیری سرویسهای وب
در سالهای اخیر این شیوهی کاری تغییر کرده و بیشتر بر اساس بکارگیری برنامههای مبتنی بر سرویسها شدهاست. برای مثال برای این مورد استاندارد WS-Security مربوط به WCF ارائه شدهاست که باز هم مرتبط است به برنامههای یک دومین و یا یک Application pool. اگر تعداد دومینها بیشتر شوند و نیاز به ارتباط امن بین آنها باشد، استاندارد SAML 2.0 مورد استفاده قرار میگرفت که هدف از آن، انتقال امن اعتبارسنجی و سطوح دسترسی کاربران بین دومینهای مختلف است. همانطور که ملاحظه میکنید تمام این برنامهها و استانداردها، داخل دیوارهای یک شرکت و یک دومین زندگی میکنند.
عصر شروع بهکارگیری Restful-API's
پس از آن باز هم شیوهی طراحی برنامههای تغییر کرد و شروع به ایجاد Restful-API's و HTTP API's کردیم. اینها دیگر الزاما داخل یک دومین ارائه نمیشوند و گاهی از اوقات حتی تحت کنترل ما هم نیستند. همچنین برنامههای ارائه شده نیز دیگر thick clients نیستند و ممکن است برنامههای سمت کلاینت Angular و یا حتی موبایل باشند که مستقیما با سرویسهای API برنامهها کار میکنند. حتی ممکن است یک API را طراحی کنیم که با یک API دیگر کار میکند.
در این حالت دیگر نمیتوان این APIها را با نگهداری آنها داخل دیوارهای یک شرکت محافظت کرد. اگر قرار است با یک HTTP API کار کنیم، این API باید عمومی باشد و در اینجا دیگر نمیتوان از روش Forms Authentication استفاده کرد. زیرا این روش اعتبارسنجی مختص برنامههای سمت سرور قرار گرفتهی در یک دومین طراحی شدهاست و آنچنان سازگاری با برنامههای سمت کلاینت و موبایل خارج از دیوارهای آن ندارد. همچنین ارسال نام کاربری و کلمهی عبور به ازای هر درخواست نیز روشی بسیار بدوی و نا امن است. اینجا است که عصر امن سازی برنامهها به کمک توکنها شروع میشود. با استفادهی از توکنها، بجای هر بار ارسال نام کاربری و کلمهی عبور به ازای هر درخواست از API، صرفا لیست سطوح دسترسی امضا شدهی به امکاناتی خاص، ارسال میشوند.
عصر شروع بهکارگیری Security Tokens
بنابراین در اینجا نیاز به برنامهای برای تولید توکنها و ارسال آنها به کلاینتها داریم. روش متداول پیاده سازی آن، ساخت یک برنامهی ابتدایی، برای دریافت نام کاربری و کلمهی عبور از کاربران و سپس بازگشت یک JSON Web Token به آنها است که بیانگر سطوح دسترسی آنها به قسمتهای مختلف برنامه است و کاربران باید این توکن را به ازای هر درخواستی به سمت سرور (بجای نام کاربری و کلمهی عبور و خود) ارسال کنند.
مشکل این روش در اینجا است که آن برنامهی خاص، باید از نام کاربری و کلمهی عبور کاربران مطلع باشد تا بتواند توکن مناسبی را برای آن کاربر خاص تولید کند. هر چند این روش برای یک تک برنامهی خاص بسیار مناسب به نظر میرسد، اما در یک شرکت، دهها برنامه مشغول به کارند و به اشتراک گذاری نام کاربری و کلمهی عبور کاربران، با تک تک آنها ایدهی مناسبی نیست و پس از مدتی از کنترل خارج خواهد شد. برای مثال کاربری در یک برنامه، کلمهی عبور خود را تغییر میدهد اما در برنامهای دیگر خیر و همین مسالهی عدم هماهنگی بین برنامهها و همچنین بخشهای مختلف یک شرکت، مدیریت یک دست برنامهها را تقریبا غیر ممکن میکند. همچنین در اینجا برنامههای ثالث را نیز باید در نظر داشت که آیا ضروری است آنها به ریز اطلاعات کاربران شرکت دسترسی پیدا کنند؟
به علاوه مشکل دیگر توسعهی این نوع برنامههای صدور توکن خانگی، اختراع مجدد چرخ است. در اینجا برای بهبود امنیت برنامه باید منقضی شدن، تمدید، امضای دیجیتال و اعتبارسنجی توکنها را خودمان پیاده سازی کنیم. توسعهی یک چنین سیستمی اگر غیرممکن نباشد، بسیار سخت و پیچیده است و همچنین باید باگهای امنیتی ممکن را نیز مدنظر داشت.
بنابراین تا اینجا به این نتیجه رسیدهایم که دیگر نمیخواهیم مدیریت نام کاربری و کلمهی عبور کاربران را در سطح هیچکدام از برنامههای خود انجام دهیم و هیچکدام از آنها قرار نیست دریافت کنندهی این اطلاعات باشند. قرار است این کار، به یک تک برنامهی مرکزی مخصوص اینکار منتقل شود و برای اینکار نیاز به پروتکلی امن است که بتوان این توکنهای تولیدی را ارسال و پردازش کرد.
حرکت به سمت «تامین کنندهی هویت مرکزی»
در گذشته، هر تک برنامهای دارای صفحهی لاگین و امکانات مدیریت کاربران آن، تغییر کلمهی عبور، تنظیم مجدد آن و اینگونه عملیات بود. اینروزها دیگر چنین کاری مرسوم نیست. این وظیفهی برنامهی شما نیست که بررسی کند کاربر وارد شدهی به سیستم کیست و آیا ادعای او صحیح است یا خیر؟ این نوع عملیات وظیفهی یک Identity provider و یا به اختصار IDP است. کار IDP اعتبارسنجی کاربر و در صورت نیاز، ارائهی اثبات هویت کاربر، به برنامهی درخواست کنندهاست.
در یک IDP عملیاتی مانند ثبت کاربران و مدیریت آنها انجام میشود. اینجا است که مفاهیمی مانند قفل کردن اکانت و یا تغییر کلمهی عبور و امثال آن انجام میشود و نه اینکه به ازای هر برنامهی تهیه شدهی برای یک شرکت، آن برنامه راسا اقدام به انجام چنین عملیاتی کند. به این ترتیب میتوان به امکان استفادهی مجدد از اطلاعات هویت کاربران و سطوح دسترسی آنها در بین تمام برنامههای موجود رسید.
همچنین با داشتن یک برنامهی IDP خوب پیاده سازی شده، از توزیع باگهای امنیتی مختلف در بین برنامههای گوناگون تهیه شده که هر کدام سیستم امنیتی خاص خودشان را دارند، جلوگیری خواهد شد. برای مثال فرض کنید میخواهید الگوریتم هش کردن پسوردهای سیستم را که امروز نا امن اعلام شدهاست، تغییر دهید. با داشتن یک IDP، دیگر نیازی نیست تا تمام برنامههای خود را برای رفع یک چنین باگهایی، تک تک تغییر دهید.
به علاوه این روزها روش استفادهی از نام کاربری و کلمهی عبور، تنها راه ورود به یک سیستم نیست و استفاده از کلیدهای دیجیتال و یا روشهای ویژهی ابزارهای موبایل نیز به این لیست اضافه شدهاند.
حرکت به سمت استاندارد OAuth 2
OAuth 2.0 پروتکلی است استاندارد، برای Authorization امن کاربران، توسط برنامههای وب، موبایل و دسکتاپ. به این ترتیب میتوان امکان دسترسی یک برنامه را به یک API، به نحوی استاندارد و امن میسر ساخت. OAuth 2.0 یک توکن دسترسی (Access token) را تولید میکند و در اختیار کلاینت قرار میدهد. سپس آن کلاینت با ارسال این توکن به API مدنظر، امکان دسترسی به امکانات مختلف آنرا خواهد یافت. به علاوه چون ماهیت برنامههای کلاینت وب و غیر وب متفاوت است، این استاندارد نحوهی دریافت چنین توکنی را برای برنامههای مختلف نیز تعریف میکند. به این ترتیب موارد مشترکی مانند تولید و نحوهی انتقال توکنها به کلاینتهای مختلف توسط این پروتکل استاندارد بیان میشود. در این حالت راهحلهای خانگی ما تبدیل به راهحلهایی میشوند که استاندارد OAuth 2.0 را پیاده سازی کرده باشند. بنابراین IDP ما باید بر مبنای این استاندارد تهیه شده باشد. برای مثال IdentityServer که در این سری بررسی خواهد شد و یا Azure Active Directory، نمونهای از IDPهایی هستند که این استاندارد را کاملا پیاده سازی کردهاند.
البته باید دقت داشت که این توکنهای دسترسی، تنها سطوح دسترسی به منابع API را مشخص میکنند و یا به عبارتی عملیات Authorization توسط آنها میسر میشود. عملیات ورود به سیستم اصطلاحا Authentication نام دارد و توسط استاندارد دیگری به نام OpenID Connect مدیریت میشود.
حرکت به سمت استاندارد OpenID Connect
OpenID Connect یک لایهی امنیتی بر فراز پروتکل OAuth 2.0 است که به اختصار به آن OIDC نیز گفته میشود. توسط آن یک کلاینت میتواند یک Identity token را علاوه بر Access token درخواست کند. از این Identity token برای ورود به برنامهی کلاینت استفاده میشود (Authentication) و پس از آن، برنامهی کلاینت بر اساس سطوح دسترسی تعریف شدهی در Access token، امکان دسترسی به امکانات مختلف یک API را خواهد یافت (Authorization). همچنین OpenID Connect امکان دسترسی به اطلاعات بیشتری از یک کاربر را نیز میسر میکند.
بنابراین OpenID Connect پروتکلی است که در عمل استفاده میشود و توسعه دهنده و جایگزین کنندهی پروتکل OAuth 2.0 میباشد. هرچند ممکن است در بسیاری از منابع صرفا به OAuth 2.0 بپردازند، اما در پشت صحنه با همان OpenID Connect کار میکنند.
مزیت دیگر کار با OpenID Connect، عدم الزام به استفادهی از API، در برنامهای خاص و یا قدیمی است. اگر برنامهی وب شما با هیچ نوع API ایی کار نمیکند، باز هم میتوانید از امکانات OpenID Connect بهرهمند شوید.
چندی قبل مطلب «نمایش تاریخ شمسی توسط JavaScript در AngularJS» را در این سایت مطالعه کردید. در اینجا قصد داریم معادل Angular آنرا تهیه کنیم (واژهی AngularJS به نگارشهای 1x اشاره میکند و Angular به تمام نگارشهای پس از 2).
نصب پیشنیازهای کار با moment-jalaali
ابتدا نیاز است بستهی npm این کتابخانه را نصب کنیم که به همراه فایلهای js مرتبط با آن میباشد:
سپس جهت بهبود تجربهی کاربری با آن در IDEهای امروزی، خصوصا VSCode، بهتر است typings آنرا نیز نصب کنیم؛ تا علاوه بر داشتن Intellisense، بتوان به صورت strongly typed با آن کار کرد:
VSCode به صورت خودکار پوشهی مخصوص node_modules\@types را تحت نظر قرار میدهد و نصب بستههای typings در آن، سبب بارگذاری آنی آنها خواهد شد.
به علاوه اگر به فایل tsconfig.json واقع در ریشهی پروژه نیز دقت کنید، وجود تعریف ذیل، امکان خوانده شدن این تعاریف را توسط کامپایلر TypeScript میسر میکند:
نحوهی کار Strongly Typed با کتابخانهی moment-jalaali در برنامههای مبتنی بر TypeScript
پس از نصب پیشنیازهای یاد شده، ابتدا برای دسترسی به امکانات این کتابخانه، ماژول آنرا import میکنیم:
- پس از import ماژولی به نام moment-jalaali، اکنون نحوهی استفادهی از آنرا در متد persianDateTests مشاهده میکنید.
- متد momentJalaali.loadPersian باید تنها یکبار فراخوانی شود. کار آن تبدیل نامهای روزها و ماههای میلادی، به شمسی است.
- پس از آن از طریق متد format آن، میتوان انواع و اقسام حالات مختلف را بررسی کرد که در اینجا سه نمونه را مشاهده میکنید.
نوشتن یک Pipe سفارشی برای تبدیل تاریخهای میلادی دریافتی از سرور به قالب شمسی
پس آشنا شدن با نحوهی استفادهی از این کتابخانه در یک برنامهی تایپاسکریپتی، تبدیل کردن آن به یک Pipe سفارشی بسیار سادهاست. برای این منظور ابتدا یک Pipe جدید را به ماژول فرضی custom-pipe.module اضافه میکنیم:
با این محتوا:
در اینجا نیز ابتدا ماژول moment-jalaali تعریف شدهاست و سپس توسط آن، value به عنوان پارامتر متد momentJalaali و args به عنوان پارامتر متد format ارسال شدهاند. در حین استفادهی از Pipe، مقدار value همان تاریخ دریافتی است و args به فرمت خاصی که توسط استفاده کننده مشخص میشود، تنظیم خواهد شد.
به این ترتیب میتوان یک چنین تبدیلات سمت کاربری را انجام داد که نمونهای از خروجی آنرا در تصویر فوق نیز ملاحظه میکنید:
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید.
نصب پیشنیازهای کار با moment-jalaali
ابتدا نیاز است بستهی npm این کتابخانه را نصب کنیم که به همراه فایلهای js مرتبط با آن میباشد:
npm install moment-jalaali --save
سپس جهت بهبود تجربهی کاربری با آن در IDEهای امروزی، خصوصا VSCode، بهتر است typings آنرا نیز نصب کنیم؛ تا علاوه بر داشتن Intellisense، بتوان به صورت strongly typed با آن کار کرد:
npm install @types/moment-jalaali --save-dev
VSCode به صورت خودکار پوشهی مخصوص node_modules\@types را تحت نظر قرار میدهد و نصب بستههای typings در آن، سبب بارگذاری آنی آنها خواهد شد.
به علاوه اگر به فایل tsconfig.json واقع در ریشهی پروژه نیز دقت کنید، وجود تعریف ذیل، امکان خوانده شدن این تعاریف را توسط کامپایلر TypeScript میسر میکند:
{ "typeRoots": [ "node_modules/@types" ] }
نحوهی کار Strongly Typed با کتابخانهی moment-jalaali در برنامههای مبتنی بر TypeScript
پس از نصب پیشنیازهای یاد شده، ابتدا برای دسترسی به امکانات این کتابخانه، ماژول آنرا import میکنیم:
import * as momentJalaali from "moment-jalaali"; export class MomentJalaaliTestComponent implements OnInit { now: string; nowLongDateFormat: string; nowExtraLongDateFormat: string; ngOnInit() { this.persianDateTests(); } persianDateTests() { // https://github.com/jalaali/moment-jalaali momentJalaali.loadPersian(/*{ usePersianDigits: true }*/); // نمایش فارسی نام ماهها، روزها و امثال آن this.now = momentJalaali().format("jYYYY/jMM/jDD HH:mm"); this.nowLongDateFormat = momentJalaali().format("jD jMMMM jYYYY [ساعت] LT"); this.nowExtraLongDateFormat = momentJalaali().format( "dddd، jD jMMMM jYYYY [ساعت] LT" ); } }
- متد momentJalaali.loadPersian باید تنها یکبار فراخوانی شود. کار آن تبدیل نامهای روزها و ماههای میلادی، به شمسی است.
- پس از آن از طریق متد format آن، میتوان انواع و اقسام حالات مختلف را بررسی کرد که در اینجا سه نمونه را مشاهده میکنید.
نوشتن یک Pipe سفارشی برای تبدیل تاریخهای میلادی دریافتی از سرور به قالب شمسی
پس آشنا شدن با نحوهی استفادهی از این کتابخانه در یک برنامهی تایپاسکریپتی، تبدیل کردن آن به یک Pipe سفارشی بسیار سادهاست. برای این منظور ابتدا یک Pipe جدید را به ماژول فرضی custom-pipe.module اضافه میکنیم:
ng g p CustomPipe/moment-jalaali -m custom-pipe.module
import { Pipe, PipeTransform } from "@angular/core"; import * as momentJalaali from "moment-jalaali"; @Pipe({ name: "momentJalaali" }) export class MomentJalaaliPipe implements PipeTransform { transform(value: any, args?: any): any { return momentJalaali(value).format(args); } }
به این ترتیب میتوان یک چنین تبدیلات سمت کاربری را انجام داد که نمونهای از خروجی آنرا در تصویر فوق نیز ملاحظه میکنید:
<h2>Server side dates:</h2> <div *ngFor="let date of dates"> <span dir="ltr">{{date | momentJalaali:'jYYYY/jMM/jDD hh:mm' }}</span>, <span dir="rtl">{{date | momentJalaali:'jD jMMMM jYYYY [ساعت] LT'}}</span> </div>
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید.
نظرات مطالب
AngularJS #1
به شدت دنبال آموزش angularjs بودم. سپاس و چند سوال.
- آیا با استفاده از angularjs برای یک SPA دیگر نیازی به asp.net mvc خواهد بود؟
-کامپایلر ویژوال استودیو به خوبی برای razor کار میکند و بسیار intellisence قوی دارد و امکانات Strongly typed نیز دارد. آیا این امکانات برای angular نیز موجود است تا خطایابی راحتتر شود؟
- من یک اپلیکیشن دارم که کاربر هربار یکی از آیتمهای منو را انتخاب میکند و برای آن یک ویو بصورت partialview درون یک تب لود میشود. هر ویو ، فایل جاوااسکریپت مخصوص به خود دارد. کاربر میتواند چندین ویوی مجزا را درون تبها باز کند و بین آنها جابه جا شود. اما مدیریت دستی آنها بسیار سخت شده است. آیا انگولار امکان نمایش چند ویو را بطور همزمان و جابه جا شدن بین آنها را میدهد.( بدون بروز تداخل بین فایلهای جاوا اسکریپت مربوط به هر ویو).
با تشکر.
اولین کاری را که میتوان پس از نصب Angular CLI انجام داد، ایجاد یک برنامهی جدید است و نمونهای از آنرا در قسمت قبل بررسی کردیم. در ادامه میخواهیم به پارامترهای بیشتر مرتبط با آن و همچنین نحوهی سفارشی سازی ایجاد برنامههای جدید بپردازیم.
ایجاد برنامههای جدید توسط Angular CLI
دستور خط فرمان ابتدایی ایجاد یک برنامهی جدید توسط Angular CLI به صورت ذیل است
در اینجا ng همان Angular CLI است. new عملی است که قرار است رخ دهد و my-app یک نام دلخواه میباشد.
پس از اجرای این دستور، برنامهی جدید ایجاد شده، در پوشهی جدید my-app قرار میگیرد.
گزینهی دیگر این دستور، استفاده از پرچم dry-run است:
کار این پرچم صرفا گزارش دادن جزئیات عملیات ng new است؛ بدون اینکه فایلی را تولید کند. به این ترتیب میتوان برآوردی را از فایلهای تولید شدهی توسط فرامین ng، پیش از تولید واقعی آنها، مشاهده کرد. برای مثال:
همانطور که مشاهده میکنید، در ابتدای کار پیامی را مبنی بر عدم نوشته شدن این فایلها بر روی فایل سیستم، ارائه دادهاست.
گزینهی دیگر دستور ng new را که در قسمت قبل ملاحظه کردید:
کار پرچم skip-install عدم فراخوانی خودکار دستور npm install است که سبب خواهد شد، برنامه بدون نصب وابستگیهای npm آن، با سرعت هرچه بیشتر، ایجاد شود. از این گزینه میتوان جهت مشاهدهی ساختار فایلهای تولیدی استفاده کرد و در نهایت در این حالت باید دستور npm install را به صورت دستی فراخوانی کرد. پرچم dry-run نیز skip-install را به صورت ضمنی به همراه دارد.
برای مشاهدهی سایر پرچمهای مرتبط با دستور ng new میتوان از پرچم help استفاده کرد:
بررسی فایل angular-cli.json.
فایل angular-cli.json. حاوی تنظیمات Angular CLI است.
در ابتدای این فایل، نام برنامهی جدید را مشاهده میکنید. این نام، همانی است که توسط دستور ng new my-app تعیین گردید.
سپس محل پوشهی source برنامه و همچنین خروجی نهایی آن، مشخص میشوند:
یکی از تنظیمات مهم این فایل، مقدار prefix است:
از این مقدار برای تنظیم مقدار prefix تمام کامپوننتها و دایرکتیوهای تولیدی توسط Angular CLI استفاده میشود. برای مثال اگر به فایل src\app\app.component.ts دقت کنید:
نام selector آن با app- شروع شدهاست که این app، از مقدار prefix فایل angular-cli.json. دریافت شدهاست.
تغییر این مقدار صرفا بر روی کامپوننتهای جدید تولید شدهی توسط Angular CLI تاثیرگذار خواهند بود. اگر میخواهید در ابتدای کار تولید یک برنامه، این مقدار را مشخص کنید، میتوان از پرچم prefix استفاده کرد و در صورت عدم ذکر آن، مقدار پیش فرض app برای آن درنظر گرفته میشود:
عدم ایجاد مخزن Git به همراه ng new
با صدور فرمان ng new، کار ایجاد یک مخزن Git نیز به صورت خودکار انجام خواهد شد. برای نمونه اگر خواستید برنامهای را بدون نصب وابستگیها، بدون ایجاد تستها و بدون ایجاد مخزن git آن تولید کنید، میتوان از دستور ذیل استفاده کرد:
استفادهی از sass بجای css توسط Angular CLI
سیستم Build همراه با Angular CLI مبتنی بر webpack است و به خوبی قابلیت پردازش فایلهای sass را نیز دارا است. اگر خواستید حالت پیش فرض تولید فایلهای css این ابزار را که در فایل angular-cli.json. نمونهای از آن ذکر شدهاست، به همراه فایلهایی مانند app.component.css، به sass تغییر دهید:
تنها کافی است پرچم style را با sass مقدار دهی کرد که حالت پیش فرض آن css است:
با ذکر این پرچم، تغییرات فایل angular-cli.json به صورت ذیل خواهند بود:
و حتی کامپوننت src\app\app.component.ts نیز به همراه شیوهنامهای از نوع sass که در حین ارائه نهایی توسط webpack به صورت خودکار پردازش میشود (بدون نیاز به تنظیمات اضافهتری)، مقدار دهی شدهاست:
و یا حتی اگر علاقمند به استفادهی از less باشید نیز میتوان پرچم style less-- را استفاده نمود.
انجام تنظیمات مسیریابی پیش فرض پروژه جدید توسط Angular CLI
حالت پیش فرض تولید برنامههای جدید Angular CLI به همراه تنظیمات مسیریابی آن نیست. اگر علاقمند هستید تا مبحث مسیریابی را خلاصه کرده و به سرعت تنظیمات ابتدایی مسیریابی را توسط این ابزار تولید کنید، میتوان پرچم routing را نیز در اینجا ذکر کرد:
در این حالت اگر به پوشهی src\app مراجعه کنید، فایل جدید app-routing.module.ts را نیز مشاهده خواهید کرد که AppRoutingModule پیش فرضی در آن تنظیم شدهاست و آمادهی استفاده میباشد.
همچنین فایل app.module.ts را نیز اندکی تغییر داده و این AppRoutingModule جدید را نیز به آن معرفی کردهاست.
به این ترتیب ارتباطات ابتدایی مورد نیاز سیستم مسیریابی برقرار شده و قابل استفادهاست. بنابراین ذکر پرچم routing میتواند یکی از پرچمهای اصلی ایجاد برنامههای جدید مبتنی بر Angular CLI باشد.
اجرای ابتدایی یک برنامهی مبتنی بر Angular CLI
پس از انتخاب پرچمهای مناسب جهت ایجاد یک پروژهی جدید مبتنی بر Angular CLI و همچنین نصب وابستگیهای آنها و یا عدم ذکر پرچم skip-install، اکنون نوبت به اجرای این پروژهاست. به همین جهت از طریق خط فرمان به ریشهی پوشهی برنامهی جدید ایجاد شده، وارد شوید. سپس دستور ذیل را صادر کنید:
در اینجا o- به معنای open است؛ یا گشودن آن در یک مرورگر. به این ترتیب کار کامپایل برنامه صورت گرفته و توسط مرورگر پیشفرض سیستم به صورت خودکار باز خواهد شد. آدرس پیش فرض آن نیز به صورت ذیل است:
نکتهی جالب این وب سرور در این است که تغییرات شما را به صورت خودکار دنبال کرده و بلافاصله ارائه میدهد. برای مثال فایل src\app\app.component.html را گشوده و به صورت ذیل تغییر دهید:
پس از ذخیرهی آن، بلافاصله خروجی نهایی را در مرورگر خواهید دید.
تغییر پیش فرضهای عمومی Angular CLI
تا اینجا مشاهده کردیم که اگر بخواهیم مقدار prefix پیش فرض را که به app تنظیم شدهاست به myCompany تغییر دهیم، یا میتوان از پرچم prefix در ابتدای کار فراخوانی دستور ng new استفاده کرد و یا میتوان فایل angular-cli.json. را نیز دستی ویرایش نمود. برای تغییر عمومی و سراسری مقدار پیش فرض app میتوان از دستور ng set استفاده کرد:
دستور اول فایل angular-cli.json. پروژهی جاری را ویرایش میکند و دستور دوم، فایل angular-cli.json سراسری Angular CLI را مقدار دهی خواهد کرد (با توجه به سوئیچ g- آن). البته بدیهی است ویرایشگرهای امروزی به خوبی قابلیت ویرایش فایلهای json را ارائه میدهند و شاید نیازی به استفادهی از این دستورات،حداقل برای اعمال تغییرات محلی نباشد.
و یا اگر بخواهید نوع شیوهنامهی مورد استفاده را ویرایش کنید، میتوان از یکی از دو دستور ذیل استفاده کرد (اولی محلی است و دومی عمومی):
اجرای امکانات Linting پروژههای مبتنی بر Angular CLI
برای بررسی کیفیت کدهای نوشته شده، میتوان از امکانات Linting استفاده کرد. برای این منظور تنها کافی است دستور ذیل را در ریشهی پروژه اجرا نمود:
برای مشاهدهی تمام گزینههای آن دستور زیر را صادر کنید:
اگر علاقمند هستید تا خروجی این ابزار، با رنگهای بهتری نمایش داده شوند، میتوان از دستور ذیل استفاده کرد:
به علاوه این ابزار قابلیت رفع مشکلات را با اعمال تغییراتی در کدهای موجود نیز به همراه دارد:
برای این منظور میتوان از پرچم fix آن استفاده کرد.
یک مثال: فایل src\app\app.component.ts را باز کنید و به عمد تعدادی مشکل را در آن ایجاد نمائید. برای نمونه دو سطر ابتدایی آنرا به صورت ذیل تغییر دهید:
اکنون اگر ng lint را اجرا کنیم، به خروجی ذیل خواهیم رسید:
عنوان میکند که بهتر است number به صورت یک const تعریف شود و همچنین یک سمیکالن در سطر اول فراموش شدهاست.
اکنون اگر دستور ng lint --fix را فراخوانی کنیم، تغییرات ذیل به فایل src\app\app.component.ts اعمال خواهند شد:
به صورت خودکار، به سطر اول، یک سمیکالن را اضافه کرده و همچنین سطر دوم را نیز به const تبدیل کردهاست.
ایجاد برنامههای جدید توسط Angular CLI
دستور خط فرمان ابتدایی ایجاد یک برنامهی جدید توسط Angular CLI به صورت ذیل است
> ng new my-app
پس از اجرای این دستور، برنامهی جدید ایجاد شده، در پوشهی جدید my-app قرار میگیرد.
گزینهی دیگر این دستور، استفاده از پرچم dry-run است:
> ng new my-app --dry-run
>ng new my-app --dry-run installing ng You specified the dry-run flag, so no changes will be written. create .editorconfig create README.md create src\app\app.component.css create src\app\app.component.html . . . Project 'my-app' successfully created.
گزینهی دیگر دستور ng new را که در قسمت قبل ملاحظه کردید:
> ng new my-app --skip-install
برای مشاهدهی سایر پرچمهای مرتبط با دستور ng new میتوان از پرچم help استفاده کرد:
> ng new --help
بررسی فایل angular-cli.json.
فایل angular-cli.json. حاوی تنظیمات Angular CLI است.
در ابتدای این فایل، نام برنامهی جدید را مشاهده میکنید. این نام، همانی است که توسط دستور ng new my-app تعیین گردید.
"project": { "name": "my-app" },
"apps": [ { "root": "src", "outDir": "dist",
یکی از تنظیمات مهم این فایل، مقدار prefix است:
"prefix": "app",
@Component({ selector: 'app-root',
تغییر این مقدار صرفا بر روی کامپوننتهای جدید تولید شدهی توسط Angular CLI تاثیرگذار خواهند بود. اگر میخواهید در ابتدای کار تولید یک برنامه، این مقدار را مشخص کنید، میتوان از پرچم prefix استفاده کرد و در صورت عدم ذکر آن، مقدار پیش فرض app برای آن درنظر گرفته میشود:
> ng new my-project --skip-install --prefix myCompany
عدم ایجاد مخزن Git به همراه ng new
با صدور فرمان ng new، کار ایجاد یک مخزن Git نیز به صورت خودکار انجام خواهد شد. برای نمونه اگر خواستید برنامهای را بدون نصب وابستگیها، بدون ایجاد تستها و بدون ایجاد مخزن git آن تولید کنید، میتوان از دستور ذیل استفاده کرد:
> ng new my-project --skip-install --skip-git --skip-tests --skip-commit
استفادهی از sass بجای css توسط Angular CLI
سیستم Build همراه با Angular CLI مبتنی بر webpack است و به خوبی قابلیت پردازش فایلهای sass را نیز دارا است. اگر خواستید حالت پیش فرض تولید فایلهای css این ابزار را که در فایل angular-cli.json. نمونهای از آن ذکر شدهاست، به همراه فایلهایی مانند app.component.css، به sass تغییر دهید:
"styles": [ "styles.css" ], "defaults": { "styleExt": "css", "component": {} }
> ng new my-project --skip-install --style sass
"styles": [ "styles.sass" ], "defaults": { "styleExt": "sass", "component": {} }
@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.sass'] })
انجام تنظیمات مسیریابی پیش فرض پروژه جدید توسط Angular CLI
حالت پیش فرض تولید برنامههای جدید Angular CLI به همراه تنظیمات مسیریابی آن نیست. اگر علاقمند هستید تا مبحث مسیریابی را خلاصه کرده و به سرعت تنظیمات ابتدایی مسیریابی را توسط این ابزار تولید کنید، میتوان پرچم routing را نیز در اینجا ذکر کرد:
> ng new my-project --skip-install --routing
const routes: Routes = [ { path: '', children: [] } ];
imports: [ BrowserModule, FormsModule, HttpModule, AppRoutingModule ],
اجرای ابتدایی یک برنامهی مبتنی بر Angular CLI
پس از انتخاب پرچمهای مناسب جهت ایجاد یک پروژهی جدید مبتنی بر Angular CLI و همچنین نصب وابستگیهای آنها و یا عدم ذکر پرچم skip-install، اکنون نوبت به اجرای این پروژهاست. به همین جهت از طریق خط فرمان به ریشهی پوشهی برنامهی جدید ایجاد شده، وارد شوید. سپس دستور ذیل را صادر کنید:
>ng serve -o
http://localhost:4200/
نکتهی جالب این وب سرور در این است که تغییرات شما را به صورت خودکار دنبال کرده و بلافاصله ارائه میدهد. برای مثال فایل src\app\app.component.html را گشوده و به صورت ذیل تغییر دهید:
<h1> Test {{title}} </h1>
تغییر پیش فرضهای عمومی Angular CLI
تا اینجا مشاهده کردیم که اگر بخواهیم مقدار prefix پیش فرض را که به app تنظیم شدهاست به myCompany تغییر دهیم، یا میتوان از پرچم prefix در ابتدای کار فراخوانی دستور ng new استفاده کرد و یا میتوان فایل angular-cli.json. را نیز دستی ویرایش نمود. برای تغییر عمومی و سراسری مقدار پیش فرض app میتوان از دستور ng set استفاده کرد:
>ng set apps.prefix myCompany >ng set apps.prefix myCompany -g
و یا اگر بخواهید نوع شیوهنامهی مورد استفاده را ویرایش کنید، میتوان از یکی از دو دستور ذیل استفاده کرد (اولی محلی است و دومی عمومی):
>ng set defaults.styleExt sass >ng set defaults.styleExt sass -g
اجرای امکانات Linting پروژههای مبتنی بر Angular CLI
برای بررسی کیفیت کدهای نوشته شده، میتوان از امکانات Linting استفاده کرد. برای این منظور تنها کافی است دستور ذیل را در ریشهی پروژه اجرا نمود:
> ng lint
> ng lint --help
> ng lint --format stylish
>ng lint --fix
یک مثال: فایل src\app\app.component.ts را باز کنید و به عمد تعدادی مشکل را در آن ایجاد نمائید. برای نمونه دو سطر ابتدایی آنرا به صورت ذیل تغییر دهید:
import { Component } from '@angular/core' let number = 10;
>ng lint --format stylish /src/app/app.component.ts[3, 5]: Identifier 'number' is never reassigned; use 'const' instead of 'let'. /src/app/app.component.ts[1, 42]: Missing semicolon Lint errors found in the listed files.
اکنون اگر دستور ng lint --fix را فراخوانی کنیم، تغییرات ذیل به فایل src\app\app.component.ts اعمال خواهند شد:
import { Component } from '@angular/core'; const number = 10;
اشتراکها
پیش نمایش SQL Server 2019 منتشر شد
مطالب
C# 7 - Discards
در تکمیل سری بررسی ویژگیهای C# 7.0، ذکر ویژگی Discards نیز ضروری است. Discards به معنای متغیرهای محلی هستند که قابل انتساب بوده، اما قابل خواندن نیستند. دارای نامی نیستند و تنها توسط یک _ مشخص میشوند. در اینجا underscore یا _، یک واژهی کلیدی است؛ مانند var و قابلیت خوانده شدن را ندارد (نمیتواند در سمت راست یک انتساب قرار گیرد).
علت وجود Discards در C# 7.0
گاهی از اوقات میخواهیم از مقادیر بازگشت داده شدهی توسط متدها، خصوصا آرگومانهای out، صرفنظر کنیم:
در این مثال، parsedValue برای ما اهمیتی نداشته و تنها میخواهیم از خروجی متد TryParse استفاده کنیم. به علاوه میخواهیم آنرا در ادامهی کد نیز قابل دسترسی کنیم. در C# 7.0 برای رسیدن به این مقصود از Discards استفاده میشود:
در اینحالت، _ ذکر شده، در بدنهی if و یا حتی در خارج از آن، قابل دسترسی نیست و کامپایلر از آن صرفنظر میکند.
مکانهایی که میتوان از Discards در آنها استفاده کرد
پارامترهای از نوع out، یکی از مکانهایی هستند که میتوان از Discards برای معرفی آنها استفاده کرد. سایر کاربردهای آن شامل موارد ذیل میشوند:
-در تعاریف tuples برای صرفنظر کردن از پارامتری خاص (Value Tuple deconstructions)
در اینجا فرض کنید خروجی یک متد که یک tuple را بر میگرداند، شامل سه عدد است که تنها به مورد اول آنها علاقمندیم. در اینجا میتوان سایر پارامترهای صرفنظر شده را توسط _ معرفی کرد.
-در pattern matching برای صرفنظر کردن از نوعی خاص
- در پارامترهای delegates
واژهی کلیدی _
یک واژهی کلیدی زمینهای است
_ یک contextual keyword به حساب میآید؛ مانند var. به این معنا که اگر پیشتر در کدهای خود، یک متغیر محلی را به نام _ تعریف کرده باشید، با _ بکار رفتهی به صورت discard، تداخل نخواهد کرد:
در اینجا مقدار v داخل بدنهی if، برخلاف تصور false خواهد بود. علت اینجا است که اولین _ تعریف شده یک local variable است و دومین _ یک discard به حساب میآید. بنابراین مهم نیست که رشتهی TRUE قابلیت parse به true را دارد و نتیجهی true در _ پارامتر خروجی out قرار میگیرد. واژهی کلیدی _ قابلیت خواندن را نداشته و فقط مقدار متغیر محلی _ تعریف شدهی پیش از discard، خوانده خواهد شد.
قابلیت تعریف مجدد را دارد
در مثال
هرچند واژهی کلیدی _ به معنای تعریف یک متغیر محلی فقط نوشتنی است، اما قابلیت تکرار تعریف آن وجود دارد. یعنی در این حالت نیازی نیست تا دومین متغیر را با یک _ و سومین را با دو __ مشخص کرد. واژهی کلیدی _ قابلیت تعریف و استفادهی مجدد را دارد.
علت وجود Discards در C# 7.0
گاهی از اوقات میخواهیم از مقادیر بازگشت داده شدهی توسط متدها، خصوصا آرگومانهای out، صرفنظر کنیم:
if (bool.TryParse("TRUE", out parsedValue)) { /* Do your stuff */ }
if (bool.TryParse("TRUE", out bool _)) { /* Do your stuff */ }
مکانهایی که میتوان از Discards در آنها استفاده کرد
پارامترهای از نوع out، یکی از مکانهایی هستند که میتوان از Discards برای معرفی آنها استفاده کرد. سایر کاربردهای آن شامل موارد ذیل میشوند:
-در تعاریف tuples برای صرفنظر کردن از پارامتری خاص (Value Tuple deconstructions)
var (arg1, _, _) = (1, 2, 3);
-در pattern matching برای صرفنظر کردن از نوعی خاص
// in pattern matching switch (input) { case int number: Add(number); break; case object[] _: // ignore break; }
- در پارامترهای delegates
// in delegate parameters var usersWithPosts = context.Users .Join(context.Posts, user => user.UserId, post => post.UserId, (user, _) => user);
واژهی کلیدی _
یک واژهی کلیدی زمینهای است
_ یک contextual keyword به حساب میآید؛ مانند var. به این معنا که اگر پیشتر در کدهای خود، یک متغیر محلی را به نام _ تعریف کرده باشید، با _ بکار رفتهی به صورت discard، تداخل نخواهد کرد:
bool _ = false, v = false; if (bool.TryParse("TRUE", out var _)) { /* Do your stuff */ v = _; }
قابلیت تعریف مجدد را دارد
در مثال
var (arg1, _, _) = (1, 2, 3);