فصل ۶: مسیریابی Routing در انگولار ۲

Routing in Angular 2

24 اسفند 1395
angular2main-routing

امیدواریم تا به اینجای کار از سری مجموعه‌ی آموزش فارسی انگولار ۲ لذت برده باشید. در این جلسه با مبحث بسیار مهم Routing یا مسیریابی در انگولار ۲ خدمت شما خواهیم بود. در دنیای توسعه وب، مسیریابی یا Routing به معنی جداسازی نرم‌افزار در بخش‌های متفاوت بر اساس وظایفی که از طریق درخواست‌های URL‌ صادر می‌شوند، می‌باشد. به عنوان مثال وقتی شما آدرس http://www.roxo.ir/‌ را در مرورگر خود وارد کنید ممکن است route‌ یا مسیر خانه (صفحه اصلی) نمایش داده شود. یا مثلا اگر آدرس http://www.roxo.ir/about را وارد کنید با صفحه‌ی «درباره ما» روبه‌رو شوید. با ما همراه باشید تا به آموزش دقیق مبحث مسیریابی بپردازیم.

چرا به مسیریابی احتیاج داریم؟

تعریف مسیریابی در نرم‌افزار ما چندین مزیت دارد:

  • جداسازی نواحی مختلف اپلیکیشن
  • حفظ وضعیت برنامه
  • محافظ مسیرها و نواحی مختلف بر اساس تعریف قوانین

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

مسیریابی سمت-کاربر چگونه کار می‌کند؟

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

حال مسیریابی سمت-کاربر چگونه می‌باشد؟ دقیقا مشابه مسیریابی سمت-سرور است با این تفاوت که در مسیریابی سمت-کاربر برای تغییر هر صفحه نیازی به ایجاد درخواست‌های HTTP‌ به سرور نیست. در اپلیکیشن‌های انگولار به این صفحات SPA یا Single Page Apps‌ گفته می‌شود. زیرا سرور یک صفحه در اختیار ما می‌گذارد که با استفاده از JavaSctipt کد شده است. حال سوال بعدی این است که چگونه مسیرهای (routes) متفاوت در کدهای جاوا اسکریپت می‌توان ایجاد کرد؟ برای پاسخگویی به این سوال همراه ما باشید.

استفاده از تگ a

برای لینک‌دادن در صفحاتی که سمت-کاربر هستند گاها می‌توان از تگ‌های لینک‌دهی <a><a/> استفاده کرد. همانطور که در جریان هستید از این تگ برای لینک مستقیم به صفحات استفاده می‌شود:

<a name="about"><h1>درباره ما</h1></a>

و با قراردادن این تگ آدرس http://roxo.ir/#about قابل دسترس بوده که با کلیک روی عبارت «درباره ما» به صفحه‌ی موردنظر ریدایرکت می‌شویم.

حال حرکتی هوشمندانه برای ایجاد مسیرهای متفاوت در SPAها این است که مسیردهی را به گونه‌ای قابل فهم‌تر تعریف کنیم. مثلا در مثال فوق می‌خواهیم آدرس به صورت http://roxo.ir/#/about باشد که این مسیردهی به hash-base routing معروف است. با این ترفند آدرس به صورت کاملا مشخص و مجزا از علامت # تعریف می‌شود.

انقلابی به نام مسیردهی سمت-کاربر HTML5

با معرفی و ایجاد HTML5 به مرورگرها قابلیت‌های مناسبی اضافه شد که تغییرات URL‌ و ایجاد حافظه برای مرورگرها یکی از آنها بود. با استفاده از دستور history.pushState می‌توان حافظه‌ی ناوبری (navigation history) برای JavaScript را فعال کرد. حال در دنیای مدرن برنامه‌نویسی و توسعه دیگر از تگ‌های a برای لینک‌دادن استفاده نمی‌شود بلکه از pushState بهره می‌بریم.

حال در انگولار ۲، HTML5 به صورت پیشفرض فعال است ولی در انگولار ۱ باید دستور locationProvider.html5Mode(true)$ را اعمال کرد.

نوشتن اولین مسیر (routes)

در انگولار تنظیمات مسیردهی توسط نگاشت path (مسیرها) به کامپوننت انجام می‌شود. اجاره بدهید یک نرم‌افزار کوچک با چندین مسیر متفاوت ایجاد کنیم. در این مثال ۳ مسیر به شرح زیر خواهیم داشت:

  1. یک صفحه اصلی با مسیر home/#/
  2. یک صفحه درباره ما با مسیر about/#/
  3. یک صفحه تماس با ما به صورت contact/#/

و اگر کاربر مسیر /#/ را ملاحظه کرد به صفحه home ریدایرکت (راهنمایی) شود.

کامپوننت‌های مسیردهی انگولار ۲

برای تنظیمات مسیردهی سه کامپوننت تعریف می‌کنیم:

  1. تنظمیات Routes که پشتیبانی مسیرهای نرم‌افزار را به عهده دارد
  2. کامپوننت RouterOutlet که به عنوان یک کامپوننت placeholder استفاده می‌شود تا مطالب هر مسیر را توسعه دهد
  3. کامپوننت RouterLink که شامل دستوراتی برای لینک دادن به مسیرها می‌باشد

حال به تشریح هر یک از کامپوننت‌ها می‌پردازیم:

Import

برای استفاده کردن از مسیردهی در انگولار ۲ باید ابتدا ماژول angular/router@ را فراخوانی کنیم. بنابراین فایل app.module.ts‌ در مسیر basic/app/ts را باز کرده و در بخش import دو ماژول RouterModule و Routes را اضافه خواهیم کرد:

import {
    RouterModule,
    Routes
} from '@angular/router';

پس از انجام مراحل فوق در command-line دستورهای زیر را جهت ساخت کامپوننت‌های مذکور وارد کنید:

ng generate component Home

ng generate component About

ng generate component Contact

حال به تنظیمات Routes می‌پردازیم:

Routes

برای تعریف routeها تنظیماتی تحت عنوان Routes ایجاد می‌کنیم و سپس از RouteModule.forRoot(routes) برای تولید نرم‌افزار خود به همراه وابستگی‌های موردنیاز‌ آن استفاده می‌کنیم. بنابراین در مسیر app/ts/app.module.ts تنظیمات زیر را انجام می‌دهیم:

const routes: Routes = [
    { path: '', redirectTo: 'home', pathMatch: 'full' },
    { path: 'home', component: HomeComponent },
    { path: 'about', component: AboutComponent },
    { path: 'contact', component: ContactComponent },
    { path: 'contactus', redirectTo: 'contact' },
];

به چند نکته‌ اشاره خواهیم کرد:

  • path مسیر URL را مشخص می‌کند
  • component کامپوننتی را مشخص می‌کند که پس از ورود به مسیر مشخص پردازش را انجام می‌دهد
  • redirectTo برای ریدایرکت کردن یک مسیر استفاده می‌شود

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

Redirection

هنگامیکه از عبارت redirectTo استفاده می‌شود به مرورگر اطلاع می‌دهیم که اگر path مشخصی وارد شد به مسیر تعریف شده redirect کن. در مثال فوق اگر مسیر http://www.roxo.ir/#/ انتخاب شود مرورگر کاربر را به مسیر http://www.roxo.ir/home هدایت می‌کند.

مثال دیگری عبارت contacts هست که کاربر را به مسیر contact هدایت می‌کند.

نصب مسیرهای ما

با اجرای دستورهای فوق Routesها در اختیار ما قرار گرفتند و حال نوبت به نصب آنها است. برای استفاده از این مسیرها در نرم‌افزار خود باید دو فرآیند در NgModule اتفاق بی‌افتد:

  1. فراخوانی Import RouterModule
  2. نصب مسیرها با استفاده از RouterModule.forRoot(routes) در Imports NgModule

حال داخل NgModule در مسیر app/ts/app.module.ts باید کامپوننت‌ها را برای هر مسیر تعریف کرده و همچنین از ماژول RouterModule‌ استفاده کنیم. در صورتیکه تمام مراحل فوق را به درستی طی کرده باشید باید مجموعه‌ی کدهای شما شبیه ذیل باشد:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { RouterModule, Routes } from '@angular/router';

import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { AboutComponent } from './about/about.component';
import { ContactComponent } from './contact/contact.component';

const routes: Routes = [
  { path: '', redirectTo: 'home', pathMatch: 'full' },
  { path: 'home', component: HomeComponent },
  { path: 'about', component: AboutComponent },
  { path: 'contact', component: ContactComponent },
  { path: 'contactus', redirectTo: 'contact' },
];

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
    AboutComponent,
    ContactComponent,
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    RouterModule,
    Routes
  ],
  providers: [],
  bootstrap: [AppComponent]
})



export class AppModule { }

ماژول RouterOutlet و استفاده از <router-outlet>

هنگامیکه کاربر به یک صفحه می‌رود باید همواره قالب اصلی (پدر) ثابت باشد و تنها بخش‌های داخلی آن تغییر کند که برای هر مسیر متفاوت است. حال برای اینکه به انگولار ۲ این فرمان را صادر کنیم که در صورت تغییر یک صفحه تنها مطالب داخل آن تغییر کند باید از دستور RouterOutlet استفاده کرد. در نتیجه فایل template اصلی را از مسیر src/app/ تحت عنوان app.component.html باز کرد و مقادیر زیر را به آن اضافه می‌کنیم:

<div class="box box-default">
  <div class="box-header with-border">
    <h3 class="box-title"><a>منوی روکسو</a></h3>
  </div>
  <div class="box-body">
      <nav>
        <ul>
          <li><a [routerLink] = "['home']">صفحه اصلی</a></li>
          <li><a [routerLink] = "['about']">درباره روکسو</a></li>
          <li><a [routerLink] = "['contact']">تماس با روکسو</a></li>
        </ul>
      </nav>

    <router-outlet></router-outlet>
  </div>
  <!-- /.box-body -->
</div>

همانطور که در کدهای بالا مشاهده می‌کنید دو عبارت routerLink و router-outlet وجود دارند که برای شما ناآشنا هستند.توضیحات زیر را مطالعه بفرمایید:

[routerLink]: این دستور برای ناوبری (navigate) مسیرها بدون رفرش شدن مجدد صفحه است. یعنی با استفاده از این دستور مسیر home/#/ بدون بارگذاری مجدد صفحه قابل دسترس خواهد بود. اگر از دستور <a/>صفحه اصلی< a href="/#/home> اجرا شود با کلیک کردن کاربر روی گزینه «صفحه اصلی» صفحه پس از بارگذاری مجدد نمایش داده خواهد شد.

router-outlet: هرگاه این تگ در قالب HTML بکارگرفته شود به سیستم ما اطلاع می‌دهد که اگر کاربر روی مسیر home/ کلیک کرد کامپوننت HomeComponent اجرا شود یا اگر روی مسیر about/ کلیک کرد کامپوننت AboutComponent اجرا شود.

نظم دادن به برنامه

حال باید تمام قطعات را کنار هم گذاشته تا بتوانیم یک برنامه‌ی واحد را ارائه دهیم. برای اینکار ابتدا نیاز داریم صفحه‌ی index.html‌ در مسیر src/ ویرایش کنیم. هر آنچه خودتان دوست دارید برای این صفحه درنظر بگیرید.

حال به پوشه‌ی src/app رفته و فایل app.module.ts‌ را باز کرده و برای تعیین مسیر پیش‌فرض اصلی (baseURL) اپلیکیشن خودتان باید به مجموعه‌ی NgModule دستور RouterModule.forRoot() را import کرده و در نهایت داخل Provider مسیر base را معرفی کنید:

RouterModule.forRoot(routes) // <-- routes

providers: [
    { provide: LocationStrategy, useClass: HashLocationStrategy },
    { provide: APP_BASE_HREF, useValue: '/' } // 
]

همانطور که ملاحظه می‌کنید داخل providers ابتدا روش بکار برده شده را که با useClass است مشخص می‌کنیم و این روش برابر HashLocationStrategy است.

حال صفحه‌ی شما با خطا روبه رو خواهد شد چون کلاس HashLocationStrategy معرفی نشده است و بنابراین برای استفاده از این روش باید ماژول آن را import کنیم و در بالای صفحه دستور زیر را اضافه خواهیم کرد:

import {LocationStrategy, HashLocationStrategy} from '@angular/common';

در صورتیکه تمام موارد فوق را رعایت کرده باشید با صفحه زیر مواجه خواهید شد:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { RouterModule, Routes } from '@angular/router';
import {LocationStrategy, HashLocationStrategy} from '@angular/common';

import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { AboutComponent } from './about/about.component';
import { ContactComponent } from './contact/contact.component';

const routes: Routes = [
  { path: '', redirectTo: 'home', pathMatch: 'full' },
  { path: 'home', component: HomeComponent },
  { path: 'about', component: AboutComponent },
  { path: 'contact', component: ContactComponent },
  { path: 'contactus', redirectTo: 'contact' },
];

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
    AboutComponent,
    ContactComponent,
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    RouterModule,
    Routes,
    RouterModule.forRoot(routes)
  ],
  providers: [
    { provide: LocationStrategy, useClass: HashLocationStrategy },
  ],
  bootstrap: [AppComponent]
})



export class AppModule { }

برای فایل‌های کامپوننت home.component.html و about.component.html و contact.component.html تغییراتی را نخواهیم داشت.

در صورتیکه صفحه localhost:4200 را باز کنید با تصویر زیر روبه‌رو خواهید شد که با کلیک روی هر یک از منوها می‌توانید بدون رفرش شدن صفحه محتوای آن صفحه را مشاهده کنید:

مثال routing در انگولار ۲

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

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

توجه: دوستان عزیز آموزش ویدیویی انگولار ۵ از مقدماتی تا پیشرفته به زبان فارسی را می‌توانید با کلیک روی اینجا یاد بگیرید. (این دوره در حال برگزاری است)

آموزش حرفه ای انگولار ۵ به زبان فارسی


فصل ۱

فصل ۲

فصل ۳

فصل ۴

فصل ۵

فصل ۶

نویسنده شوید

دیدگاه‌های شما (3 دیدگاه)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

مجتبی
17 فروردین 1397
سلام ممنون از سایت به این خوبی و کاملتون. من یه مشکل دارم جایی ندیدمش. چطور میتونم با انگولار به درگاه بانک وصل بشم.من وب سرویس php رو دارم. چطور میتونم با انگولار داده ارسال کنم بهش که وب سرویس داده ها رو بگیره و صفحه بانک رو باز کنه؟

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

پوریا نوروزی
09 بهمن 1396
سلام .... ممنون از این همه زحمتی که کشیدید آموزشتون رو تا انتها خوندم و تونستم باش یه پروژه ی تجاری کامل رو جمع کنم ... فقط توی بخش httpRequest ها یه مقدار مثالتون خیلی ساده بود ، اگه قسمت دومش رو هم اضافه کنید به عنوان بهترین آموزش فارسی ای که دیدم خواهید شد ، هر چند همین الان هم هستید ... باز هم ممنونم

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

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

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

روکسو
29 تیر 1396
با سلام سوال شما شفاف نیست لطفا مثالی را مطرح بفرمایید تا شما را بیشتر راهنمایی کنیم.

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

اشکان
29 تیر 1396
مثلا در مثال خودتون در بالا در هر صفحه که برویم هدر در بالا ثابت می ماند چون در کامپونننت پدر هست، میخوام بدونم که اگر جای نیاز باشد که در صفحه برویم که هدر در بالا وجود نداشته باشد باید چه کار کرد؟

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

روکسو
29 تیر 1396
برای اینکار باید شما یک کامپوننت به ام header ایجاد کنید و در نهایت داخل صفحه اصلی کامپوننت app.component.html تگ app-header را با شرط قرار دهید. یعنی اگر شرط شما برقرار بود هدر نمایش داده نشود و در غیراینصورف فعال باشد.

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

اشکان
29 تیر 1396
مرسی!

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.