- Webpack 2
- Angular 2
- Typescript
- Bootstrap 4
- ES 6
دریافت کتاب ng-book 2
نقشهی راه فراگیری ES6
برنامههای Vue.jsای از چندین کامپوننت برای بخش بندی هر قسمت تشکیل میشوند و این بخش بندی برای مدیریت بهتر تغییرات، خطایابی، نگهداری و استفاده مجدد (reusable) میباشد. فرض کنید تعدادی کامپوننت در برنامه داریم و اطلاعات این کامپوننتها بهم وابسته میباشند؛ بطور مثال یک کامپوننت انتخاب دسته بندی را داریم و به محض تغییر این مقدار، میخواهیم لیستی از محصولات پیشنهادی یا پرفروشِ آن دسته بندی، در کامپوننت پایین صفحه نمایش داده شود و یا خرید یک محصول را در نظر بگیرید که بلافاصله محتوای نمایش سبد خرید، بروزرسانی شود. در این مقاله ارتباط از نوع Parent و Child بین کامپوننتها بررسی میشود.
نکته: برای ارسال اطلاعات از کامپوننتِ Parent به Child، از Props استفاده میشود و برای ارتباط از Child به Parent، از emit$ استفاده میشود.
یک برنامه Vue.js با نام vue-communication-part-1 ایجاد نمایید. سپس دو کامپوننت را با نامهای Parent و Child، در پوشه components ایجاد کنید:
در کامپوننت Parent، یک تابع با نام increase وجود دارد که مقدار متغیر parentCounter را افزایش میدهد. چون قصد داریم مقدار متغیر parentCounter در کامپوننت Child نیز بروزرسانی شود، آن را به کامپوننت Child پاس میدهیم:
<Child :childCounter="parentCounter"/>
محتوای کامپوننت Parent:
<template> <div> <div> <h2>Parent Component</h2> <!-- را نمایش میدهید parentCounter مقدار --> <h1>{{ parentCounter }}</h1> <button @click="increase">Increase Parent</button> </div> <div> <!-- پاس میدهید Child در کامپوننت childCounter را به پراپرتی parentCounter مقدار --> <!--از طریق decreaseParent سبب اتصال و فراخوانی تابع @callDecreaseParent به decreaseParent با انتساب --> <!-- میشود Child در کامپوننت callDecreaseMethodInParent تابع --> <Child :childCounter="parentCounter" @callDecreaseParent="decreaseParent"/> </div> </div> </template> <script> //برای استفاده در کامپوننت جاری Child ایمپورت کردن کامپوننت import Child from "./Child.vue"; export default { // در این بخش متغیرهای مورد نیاز کامپوننت را تعریف میکنیم data() { return { parentCounter: 0 }; }, components: { // میتوان آرایه ای از کامپوننتها را در یک کامپوننت استفاده نمود // در این مثال فقط از یک کامپوننت استفاده شده Child }, methods: { //را یک واحد افزایش میدهد parentCounter این متد مقدار increase() { this.parentCounter++; }, decreaseParent() { this.parentCounter--; } } }; </script> <style> .parent-block, .child { text-align: center; margin: 20px; padding: 20px; border: 2px gray solid; } </style>
در کامپوننت Child قصد دریافت مقدار پراپرتیِ childCounter را داریم که از طریق کامپوننت Parent، مقدارش تنظیم و بروزرسانی میشود. به این منظور در قسمت props یک متغیر بنام childCounter را ایجاد میکنیم.
Data is the private memory of each component where you can store any variables you need. Props are how you pass this data from a parent component down to a child component
محتوای کامپوننت Child
<template> <div> <h3>Child Component</h3> <!-- را نمایش میدهید childCounter مقدار --> <h3>{{ childCounter }}</h3> <button @click="increase">Increase Me</button> <button @click="callDecreaseMethodInParent">Call Decrease Method In Parent</button> </div> </template> <script> export default { // استفاده میشود Child به Parent برای ارتباط بین کامپوننت props از props: { childCounter: Number }, data() { return {}; }, methods: { //را یک واحد افزایش میدهد childCounter این متد مقدار increase() { this.childCounter++; }, // فراخوانی میکند Parent را در کامپوننت decreaseParent تابع callDecreaseMethodInParent() { this.$emit("callDecreaseParent"); } } }; </script>
محتوای کامپوننت اصلی برنامه App.vue:
<template> <div id="app"> <img alt="Vue logo" src="./assets/logo.png"> <parent></parent> </div> </template> <script> import Parent from "./components/Parent.vue"; export default { name: "app", components: { parent: Parent } }; </script> <style> #app { width: 50%; margin: 0 auto; text-align: center; } </style>
اکنون برنامه را با دستور زیر اجرا کنید:
npm run serve
بعد از اجرای دستور فوق، روی گزینه زیر ctrl+click میکنیم تا نتیجه کار در مرورگر قابل رویت باشد:
نمایش صفحه زیر نشان دهندهی درستی انجام کار تا اینجا است:
اکنون روی دکمهی Increase Parent کلیک میکنیم. همزمان مقدار شمارشگر، در هر دو کامپوننت Parent و Child افزایش مییابد و این بدین معناست که با استفاده از Props میتوانیم دادههای دلخواهی را در کامپوننت Child بروز رسانی کنیم. هر زمانی روی دکمهی Increase Me در کامپوننت Child کلیک کنیم، فقط به مقدار شمارشگر درون خودش اضافه میشود و تاثیری را بر شمارشگر Parent ندارد. در واقع یک کپی از مقدار شمارشگر Parent را درون خود دارد.
در ادامه قصد داریم بروزرسانی داده را از Child به Parent انجام دهیم. برای انجام اینکار از emit$ استفاده میکنیم. در دیکشنری Cambridge Dictionary معنی emit به ارسال یک سیگنال ترجمه شدهاست. در واقع بااستفاده از emit میتوانیم یک تابع را در کامپوننت Parent فراخوانی کنیم و در آن تابع، کد دلخواهی را برای دستکاری دادهها مینویسیم.
در تابع callDecreaseMethodInParent در کامپوننت Child، کد زیر را قرار میدهیم:
this.$emit("callDecreaseParent");
هر زمانکه این تابع اجرا شود، یک سیگنال از طریق کد زیر برای کامپوننت Parent ارسال میشود:
<Child @callDecreaseParent="decreaseParent"/>
در کد فوق مشخص شده که با ارسال سیگنال callDecreaseParent، تابع decreaseParent در کامپوننت Parent فراخوانی شود.
نکته: برای اجرای برنامه و دریافت پکیجهای مورد استفاده در مثال جاری، نیاز است دستور زیر را اجرا کنید:
npm install
چند نکته
this.$emit //dispatches an event to its parent component
کد فوق سبب اجرای یک تابع در کامپوننتِ Parent خودش میشود.
this.$parent // gives you a reference to the parent component
ارجاعی به کامپوننت Parent خودش را فراهم میکند:
this.$root // gives you a reference to the root component
زمانیکه چندین کامپوننت تو در تو را داریم یا به اصطلاح nested component، سبب ارجاعی به بالاترین کامپوننت Parent میگردد.
this.$parent.$emit // will make the parent dispatch the event to its parent
سبب اجرای تابعِ Parent کامپوننتِ Parent جاری میشود. به بیان ساده اگر این کد در کامپوننت فرزند فراخوانی شود، سبب اجرای تابعی در کامپوننت پدربزرگِ خود میشود.
this.$root.$emit // will make the root dispatch the event to itself
سبب اجرای تابعی در کامپوننت root میشود (بالاترین کامپوننتِ پدرِ کامپوننت جاری).
تابع emit$ دارای آگومانهای دیگری برای پاس دادن اطلاعات از کامپوننت Child به Parent میباشد؛ مثل زمانیکه قصد دارید اطلاعاتی در مورد محصول خریداری شده را به سبد خرید پاس دهید. در مثال دیگری که در ادامه قرار میگیرد نحوه کارکرد ارتباط کامپوننت Parent و Child را در یک برنامه بهتر تجربه میکنیم.
پیاده سازی یک سبد خرید ساده با روش مقالهی جاری
نکته: برای اجرای برنامه و دریافت پکیجهای مورد استفاده در مثال جاری، نیاز است دستور زیر را اجرا کنید:
npm install
همچنین نیاز هست تا پکیچ node-sass را با دستور زیر برای این مثال نصب کنید.
npm install node-sass
* نکته: پروژه انگیولار متریال ۲ در زمان نوشتن این مقاله به تازگی نسخه بتا ۵ را ارائه داده و همچنان در حال توسعه است. این بدان معنی است که ممکن است همه چیز به سرعت تغییر یابد.
مقدمه
انگیولار متریال ۲ همانند انگیولار متریال یک، تمامی المانهای مورد نیاز برای طراحی یک برنامه تک صفحهای را به راحتی فراهم میکند (هرچند تمامی المانهای آن در نسخه بتا پیاده سازی نشدهاند). خبر خوب اینکه، اکثر کامپوننتهای ارائه شده در انگیولار متریال ۲ از قالب راست به چپ پشتیبانی میکنند و اعمال این قالب به سادگی اضافه کردن خصوصیت dir یک المان به rtl است.
در صفحه گیتهاب انگیولار متریال ۲ آمدهاست که انگیولار متریال ۲، واسطهای کاربری با کیفیت بالا را ارائه میدهد و در ادامه منظورش را از «کیفیت بالا»، اینگونه بیان میکند:
- بینالمللی
و قابل دسترس برای همه به نحوی که تمامی کاربران میتوانند از آنها استفاده کنند
(عدم مشکل در چند زبانه بودن و پشتیبانی از قالب راست به چپ و چپ به راست) .
- دارای APIهای ساده برای توسعه دهندگان.
- رفتار مورد انتظار و بدون خطا در تمامی موردهای کاری
-
تست تمامی رفتارها توسط تست یکپارچگی (unit test ) و تست واحد ( integration test )
-
قابلیت سفارشی سازی در چارچوب طراحی متریال
-
بهرهوری بالا
-
کد تمیز و مستندات خوب
شروع کار با انگیولار متریال ۲
قدم اول: نصب angular-material و hammerjs
برای شروع بایستی Angular Material و angular animations و hammer.js را توسط npm به صورت زیر نصب کنید.
npm install --save @angular/material @angular/animations
npm install --save hammerjs
angular/material@: بسته مربوط به انگیولار متریال دو را نصب خواهد کرد.
angular/animations@: این بسته امکاناتی جهت ساخت افکتهای ویژه هنگام تغییر صفحات، یا بارگذاری المنتها را از طریق کدهای css نوشته شده، به راحتی امکانپذیر میکند.
Hammerjs: برخی از کامپوننتهای موجود در انگیولار متریال ۲ وابسته به کتابخانه Hammerjs هستند. (از جمله md-slide-toggle و md-slider, mdTooltip)
قدم دوم: معرفی کتابخانههای خارجی به angular-cli.json
"scripts": [ "../node_modules/hammerjs/hammer.min.js" ],
قدم سوم: افزودن Angular Material به ماوژل اصلی برنامه انگیولار
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http'; import { MaterialModule } from '@angular/material'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, FormsModule, HttpModule, MaterialModule, BrowserAnimationsModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
قدم چهارم: افزودن تم و آیکون
همراه با نصب Angular Material تعدادی تم از قبل ساخته شده نیز نصب خواهند شد که شامل یکسری استایل با رنگهای مشخصی هستند. از جمله این تمها عبارتند از:
- indigo-pink
- deeppurple-amber
- purple-green
- pink-bluegrey
همچنین با استفاده از Material Design icons نیز با استفاده از تگ <md-icon> به آیکونهای متریال نیز میتوان دسترسی داشت.
برای افزودن آیکونهای متریال و همچنین انتخاب یک تم از قبل ساخته شده دو خط زیر را به فایل style.css اصلی برنامه اضافه کنید.
@import '~https://fonts.googleapis.com/icon?family=Material+Icons'; @import '~@angular/material/prebuilt-themes/deeppurple-amber.css';
نکتهای که در تگ <md-icon> وجود دارد این است که این تگ انواع فونتها و آیکونهای svg را نیز پشتیبانی میکند. استفاده از آیکونهای متریال یکی از قابلیتهای این تگ محسوب میشود.
برای اطلاعات بیشتر از نحوه ساخت تم سفارشی میتوانید این لینک را دنبال کنید.
قدم آخر: انگیولار متریال آماده است!
با انجام مراحل بالا اکنون میتوانید به راحتی از کامپوننتهای متریال استفاده کنید. کافی است کدهای زیر را به فایل app.component.html اضافه کنید و یک قالب ساده برای برنامه خود بسازید.
<md-sidenav-container> <md-sidenav #end align="end" opened="true" mode="side"> <md-toolbar color="accent"> <div> <md-toolbar-row> <img src="https://material.angular.io/favicon.ico" style="height:50px;margin-top: 2px; margin-bottom: 2px;"> <span> برنامه من </span> </md-toolbar-row> </div> </md-toolbar> <md-nav-list> <md-list-item [routerLink]="['/']"> <div> <div></div> <md-icon role="img" aria-label="home">home</md-icon> <span>خانه</span> </div> </md-list-item> </md-nav-list> <md-nav-list> <md-list-item [routerLink]="['/registries']"> <div> <div></div> <md-icon role="img" aria-label="forms">content_paste</md-icon> <span>فرم</span> </div> </md-list-item> </md-nav-list> <md-nav-list> <md-list-item href="/charts"> <div> <div></div> <md-icon role="img" aria-label="charts">show_chart</md-icon> <span>نمودارها</span> </div> </md-list-item> </md-nav-list> </md-sidenav> <header> <md-toolbar color="primary"> <button md-icon-button (click)="end.toggle()"> <md-icon>menu</md-icon> </button> <span>داشبورد</span> <button md-icon-button [md-menu-trigger-for]="menu"> <md-icon>person</md-icon> </button> </md-toolbar> <md-menu x-position="before" #menu="mdMenu"> <button md-menu-item>تنظیمات</button> <button md-menu-item>خروج</button> </md-menu> </header> <main> <router-outlet></router-outlet> </main> </md-sidenav-container> <span> <button md-fab> <md-icon>check circle</md-icon> </button> </span>
همچنین کدهای css زیر را به فایل اصلی style.css اضافه کنید.
html, body, material-app, md-sidenav-container, .my-content { margin: 0; direction: rtl; width: 100%; height: 100%; } .mat-button-toggle, .mat-button-base, .mat-button, .mat-raised-button, .mat-fab, .mat-icon-button, .mat-mini-fab, .mat-card, .mat-checkbox, .mat-input-container, .mat-list, .mat-menu-item, .mat-radio-button, .mat-select, .mat-list .mat-list-item .mat-list-item-content, .mat-nav-list .mat-list-item .mat-list-item-content, .mat-simple-snackbar, .mat-tab-label, .mat-slide-toggle-content, .mat-toolbar, .mat-tooltip { font-family: 'Iranian Sans', Tahoma !important; } md-sidenav { width: 225px; max-width: 70%; } md-sidenav md-nav-list { display: block; } md-sidenav md-nav-list :hover { background-color: rgb(250, 250, 250); } md-sidenav md-nav-list .md-list-item { cursor: pointer; } .side-navigation { padding-top: 0; } md-nav-list.side-navigation a[md-list-item] > .md-list-item > span.title { margin-right: 10px; } md-nav-list.side-navigation a[md-list-item] > .md-list-item { -webkit-font-smoothing: antialiased; letter-spacing: .14px; } md-list a[md-list-item] .md-list-item, md-list md-list-item .md-list-item, md-nav-list a[md-list-item] .md-list-item, md-nav-list md-list-item .md-list-item { display: flex; flex-direction: row; align-items: center; box-sizing: border-box; height: 48px; padding: 0 16px; } button.my-fab { position: absolute; right: 20px; bottom: 10px; } md-card { margin: 1em; } md-toolbar-row { justify-content: space-between; } .done { position: fixed; bottom: 20px; left: 20px; color: white; } md-nav-list.side-navigation a[md-list-item] { position: relative; } md-list a[md-list-item], md-list md-list-item, md-nav-list a[md-list-item], md-nav-list md-list-item { display: block; } md-list a[md-list-item], md-list md-list-item, md-nav-list a[md-list-item], md-nav-list md-list-item { color: #000; } md-nav-list a { text-decoration: none; color: inherit; } a { color: #039be5; text-decoration: none; -webkit-tap-highlight-color: transparent; } .no-padding { padding: 0 !important; }
به همین راحتی برنامه نمونه با طراحی متریال آماده است.
انتشار PostSharp 6.0 RC
PostSharp 6.0 is the biggest refactoring since the 2.0 version released in July 2010. For a good cause: PostSharp 6.0 now runs natively in .NET Core 2.0. Previous versions of PostSharp executed only under .NET Framework at build time and the support for .NET Core was achieved by using a load of hacks that ended up being unmaintainable, warranting this big refactoring.
Let’s have a look at the new features of PostSharp 6.0 :
- Support for .NET Core 2.0-2.1 and .NET Standard 2.0.
- Support for Portable PDB.
- Support for C# 7.2.
- Ending the PostSharp versioning hell side-by-side: backward compatibility within the same major version.
- Logging: robustness to faults in the logging subsystem.
- Logging: no need to initialize before the first logged method is hit.
- Caching: preventing concurrent execution (locking).
- Visual Studio tooling: support for the new CPS-based project systems.
- GDPR compliance: we no longer collect your name and email for trial, nor use unsecure HTTP, nor use non-resettable user id hashes.