چگونگی روند اجرای برنامه در انگولار ۲ و برنامه‌نویسی سایت reddit - بخش ۱-۴

12 آذر 1395
4-angular2main

در بخش ۱-۳ شما موفق به تولید یک نرم‌افزار بسیار ساده شدید. همچنین با مفاهیمی چون ngFor و Input جهت تکرار و ارسال داده از کامپوننت والد به فرزند آشنا شدید. در این جلسه قصد دارم کمی دقیق‌تر و ریزتر مفاهیم خودراه‌اندازی را در انگولار ۲ مورد بررسی قرار دهیم. با ما همراه باشید.

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

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

ng serve

ng درون فایل angular-cli.json به جستجو می‌پردازد تا نقطه‌ی شروع یک اپلیکیشن را پیدا کند. حال نشان می‌دهیم که چگونه ng کامپوننتی را برای اجرا پیدا می‌کند. در سطوح بالاتر اینطوری به نظر می‌رسد:

  • angular-cli.json یک فایل main را مشخص می‌کند که به تحت عنوان main.ts نام‌گذاری شده است
  • main.ts به عنوان نقطه شروع برای اپلیکیشن ما معرفی شده و به صورت خودکار اپلیکیشن ما را اجرا می‌کند
  • فرآیند خودراه‌اندازی یک ماژول انگولار صورت می‌گیرد
  • از AppModule برای خود‌راه‌اندازی اپلیکیشن استفاده می‌شود. AppModule درون مسیر src/app/app.module.ts قرار دارد
  • AppModule مشخص می‌کند که کدام component به عنوان اولین کامپوننت استفاده می‌شود. در اکثر نرم افزارهای انگولار ۲، این کامپوننت AppComponent نام دارد.
  • AppComponent تگهای <app-user-list> را در قالب موردنظر رندر می‌کند و اجزاء را نمایش می‌دهد.

درباره این فرایند به تفصیل صحبت خواهیم کرد. اما در این مرحله روی سیستم Angular Module یا NgModules تمرکز می‌کنیم.

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

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

import { AppComponent } from './app.component';
import { HelloWorldComponent } from './hello-world/hello-world.component';
import { UserItemComponent } from './user-item/user-item.component';
import { UserListComponent } from './user-list/user-list.component';

@NgModule({
  declarations: [
    AppComponent,
    HelloWorldComponent,
    UserItemComponent,
    UserListComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

در ابتدای کار شما یک مفسر @NgModule را مشاهده می‌کنید. مشابه تمام مفسرها، کد @NgModule() یک سری اطلاعات و داده‌ها را برای کلاس AppModule فراهم می‌کند.

مفسر @NgModule سه کلید اصلی دارد: declarations, imports و bootstrap

declarations کامپوننت‌هایی که در این ماژول تعریف شده‌اند را مشخص می‌کند. شاید برای شما این سوال پیش بیاید چگونه وقتی دستور ng generate را وارد می‌کنید، یک کامپوننت با تمام الحاقات آن ساخته می‌شود! یک اصل و ایده‌ی اساسی در انگولار هست که می‌گوید:

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

imports تمام وابستگی‌های این ماژول را تعریف می‌کند. در واقع ما یک اپلیکیشن مرورگر ساخته‌ایم بنابراین باید ماژول BroserModule را import کنیم.

bootstrap به انگولار اطلاع می‌دهد که هر وقت این ماژول برای اجرای یک اپلیکیشن راه‌اندازی شد، حتما AppComponent را به عنوان بالاترین کامپوننت به کار بگیرد.

توسعه و طراحی سایت نظرسنجی با انگولار 2

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

ساخت سایت نظرسنجی مشابه reddit

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

  • کامپوننتی که برای اپلیکیشن کلیست و شامل فرمی برای ثبت مطلب جدید می‌باشد و به رنگ صورتی نمایش داده شده است.
  • کامپوننتی که برای هر مطلب می‌باشد و به رنگ سبز است.

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

در ابتدای کار بهتر است از نرم‌افزار قبلی که تحت عنوان angular2_hello_world ایجاد کردیم، چشم‌پوشی کرده و نرم‌افزاری جدید را با دستور new تولید کنید. بنابراین داریم:

ng new angular2_reddit

کامپوننت‌های نرم‌افزار

هم‌اکنون باید یک کامپوننت جدید را که دارای ویژگی‌های زیر است، بسازید:

  • ذخیره‌سازی لیست مطالب موجود
  • دارنده‌ی یک فرم برای ثبت مطالب جدید

می‌توان اصلی‌ترین کامپوننت اپلیکیشن را در مسیر src/app/app.component.ts پیدا کرد تا اطلاعات اولیه‌ای را درون آن مشابه قبل قرار داد:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app works!';
}

باید قالب این کامپوننت را که یک قالب پیش‌فرض است تغییر داده تا پیکره‌ی نرم‌افزار اصلی ما ظاهری مناسب‌تر داشته باشد، در نتیجه app.component.html را بنا به سلیقه خود طراحی کنید. برای طراحی حرفه‌ای می‌توانید از فریم‌ورک‌های CSS و HTML استفاده کرد که معروف‌ترین آنها فریم‌ورک‌های getbootstrap, getUikit, Foundation, Semantic می‌باشد. در اینجا ما از فریم ورک bootstrap استفاده می‌کنیم:

<div class="row">
<!-- Horizontal Form -->
  <div class="col-md-8 col-center-block">
    <div class="box box-info">
      <div class="box-header with-border">
        <h3 class="box-title">ثبت لینک</h3>
      </div>
      <!-- /.box-header -->
      <!-- form start -->
      <form class="form-horizontal">
        <div class="box-body">
          <div class="form-group">
            <label for="title" class="col-sm-2 control-label">عنوان مطلب</label>

            <div class="col-sm-10">
              <input type="text" class="form-control" name="title" placeholder="عنوان مطلب خود را وارد کنید">
            </div>
          </div>
          <div class="form-group">
            <label for="link" class="col-sm-2 control-label">لینک</label>

            <div class="col-sm-10">
              <input type="text" class="form-control" name="link" placeholder="لینک مطلب را وارد کنید">
            </div>
          </div>
        </div>
        <!-- /.box-body -->
        <div class="box-footer">
          <button type="submit" class="btn btn-info pull-right">ثبت</button>
        </div>
        <!-- /.box-footer -->
      </form>
    </div>
  </div>
  </div>
  <!-- /.box -->

همانگونه که مشاهده می‌کنید در template موردنظر به استثنای تگهای تزئینی HTML دو تگ اصلی input به فرم اضافه کرده‌ایم. یکی تگ title و دیگری link. در صورتیکه مرورگر خود را بروزرسانی کنید با تصویری مشابه، تصویر ذیل روبه‌رو خواهید شد:

طراحی فرم ثبت لینک و عنوان مطلب با bootstrap

اضافه کردن یک ساختار تعاملی

هم‌اکنون یک فرم با تگ‌های ورودی input داریم اما هیچ اطلاعاتی از طریق فرم ما ثبت نمی‌شود. چون در تگ دکمه <button> هیچگونه رویدادی تعریف نشده است که اگر کاربر این دکمه را فشرد عکس‌العملی نشان دهد. درواقع ما می‌خواهیم وقتی یک فرم ثبت شد تابعی فراخوانی شود. برای اینکار یک رویداد تعاملی به دکمه‌ی button خود اضافه می‌کنیم.

در عمل از انگولار درخواست می‌کنیم که نسبت به رویداد تعریف شده پاسخی ارسال کند. هر رویداد دارای یک عنوان است که در انگولار ۲ این عنوان داخل یک جفت پرانتز () تعریف می‌شود. برای مثال جهت اضافه کردن یک رویداد به هنگام کلیک کردن روی یک دکمه یا همان رویداد onClick می‌توان تابع addArticle() را فراخوانی کرد. به مثال زیر توجه کنید:

<div class="box-footer">
    <button type="submit" (click)="addArticle()"  class="btn btn-info pull-right">ثبت</button>
</div>

با اجرای دستور بالا، هر وقت روی دکمه‌ی «ثبت» کلیک شود، تابع addArticle() فراخوانی می‌شود. حال باید تابع addArticle() را داخل کلاس AppCompnent تعریف کنیم. بنابراین داریم:

export class AppComponent {
  addArticle(title: HTMLInputElement, link: HTMLInputElement): boolean {
    console.log('Adding article title: ${title.value} and link: ${link.value}');
    return false;
  }
}

همانگونه که ملاحظه می‌کنید تابع addArticle دارای دو آرگومان به نام‌های title و link است. حال نیاز به تغییرات دکمه‌ی «ثبت» داریم. زیرا باید آرگومان تابع addArticle() در دکمه تغییر کند و دو ورودی بگیرد. همچنین باید متغییرهای ارسالی به این تابع نیز در فرم template برای المان‌های input اعمال شود. بنابراین:

<div class="row">
<!-- Horizontal Form -->
  <div class="col-md-8 col-center-block">
    <div class="box box-info">
      <div class="box-header with-border">
        <h3 class="box-title">ثبت لینک</h3>
      </div>
      <!-- /.box-header -->
      <!-- form start -->
      <form class="form-horizontal">
        <div class="box-body">
          <div class="form-group">
            <label for="title" class="col-sm-2 control-label">عنوان مطلب</label>

            <div class="col-sm-10">
              <input type="text" class="form-control" name="title" placeholder="عنوان مطلب خود را وارد کنید" #newtitle>
            </div>
          </div>
          <div class="form-group">
            <label for="link" class="col-sm-2 control-label">لینک</label>

            <div class="col-sm-10">
              <input type="text" class="form-control" name="link" placeholder="لینک مطلب را وارد کنید" #newlink>
            </div>
          </div>
        </div>
        <!-- /.box-body -->
        <div class="box-footer">
          <button type="submit" (click)="addArticle(newtitle, newlink)"  class="btn btn-info pull-right">ثبت</button>
        </div>
        <!-- /.box-footer -->
      </form>
    </div>
  </div>
  </div>
  <!-- /.box -->

مطابق با تغییرات بالا در المان‌های input متغییرهایی را جهت ذخیره‌سازی اطلاعاتی که توسط کاربر نوشته می‌شوند، تعریف کردیم. این متغییرها با علامت # مشخص و به عنوان متغییرهای محلی شناخته می‌شوند. با اضافه کردن متغییرهای #title و #link به المانهای input می‌توان اطلاعات را به تابع addArticle() ارسال کرد.

برای یادآوری تغییرات انجام شده را لیست می‌کنیم:

  1. ابتدا یک دکمه جهت ثبت تغییرات ایجاد کردیم.
  2. یک تابع به نام addArticle تعریف و به این دکمه اضافه کردیم.
  3. صفت (click) را به این دکمه اضافه کرده تا به هنگام کلیک کردن روی آن، تابع addArticle‌ فراخوانی شود.
  4. صفات #newtitle و #newlink را به عنوان متغییرهای حامل اطلاعات به تگ input‌ اضافه کردیم.

این مسیر رو به جلوی ما بود، حال برای اینکه این مباحث به صورت کامل برای شما جا بیافتد یکبار دیگر از آخر به اول تمام این مراحل را ریز به ریز بررسی کرده و توضیح می‌دهیم:

اتصال مقادیر وارد شده در input به متغییرهای حامل

در تگ‌های input‌ متغییرهای محلی جهت حمل اطلاعات و ارسال آنها به تابع addArticle() ایجاد شد. این صفات به انگولار می‌گویند که اطلاعات وارد شده توسط کاربر در input را به متغیرهای #newtitle و #newlink‌ وصل کن! سینکتس #newtitle یک تصمیم (resolve) نامیده می‌شود. با این شرایط newtitle یک شیء می‌باشد که المان input DOM را نمایش می‌دهد (به طور مشخص، نوع این متغییرها HTMLInputElement می‌باشد). زیرا newtitle یک شیء است و در نتیجه مقدار ورودی متصل شده به آن با استفاده از newtitle.value قابل دسترس است.

اتصال actionها به رویدادها

در تگ button صفت (click) برای زمانیکه کاربر روی دکمه کلیک کرده بود، تعریف شده است. هنگامیکه رویداد (click) رخ دهد، تابع addArticle فراخوانی میشود که دارای دو ورودی newtitle و newlink‌ است. این تابع و دو آرگومان از کجا آمده‌اند؟

  1. addArticle یک تابع است که درون کامپوننت AppComponent تعریف شده است
  2. newtitle به صورت حامل موجود در تگ input‌ تحت عنوان title ایجاد شده است (#newtitle)
  3. newlink به صورت موجود در تگ input تحت عنوان link ایجاد شده است (#newlink)

مجموع این تفاسیر به شکل زیر خواهد بود:

<button type="submit" (click)="addArticle(newtitle, newlink)"  class="btn btn-info pull-right">ثبت</bu

تعریف Actionهای منطقی

در کلاس AppComponent تابعی تحت عنوان addArticle تعریف شده است. این تابع دو آرگومان دارد:‌ ۱) title و ۲) link. مجددا اشاره می‌کنیم که title و link هر دو شیءهایی (Object) از نوع HTMLInputElement هستند و توجه کنید که به عنوان مقادیر مستقیم inputها شناخته نمی‌شوند. برای دستیابی به مقادیر input از دستور title.value استفاده می‌کنیم. همچنین خروجی را در کنسول با دستور console.log و آرگومان‌هایش به نمایش می‌گذاریم.

export class AppComponent {
  addArticle(title: HTMLInputElement, link: HTMLInputElement): boolean {
    console.log(`Adding article title: ${title.value} and link: ${link.value}`);
    return false;
  }
}

توجه: اگر به مجموعه‌ی کد موجود در شیء console‌ دقت کنید، متوجه خواهید شد که از علامت ` یا به اصطلاح backtick استفاده شده است. این ویژگی در ES6 مطرح شده است که منجر به توسعه متغییرهای قالب می‌شود. در تابع addArticle() از عبارت ${title.value} استفاده شده است که با مقدار title.value جایگزین می‌شود.

برای نهایی کردن این قسمت روی دکمه‌ی «ثبت» کلیک کنید و درصورتیکه تمام کدها را به درستی وارد کرده باشید با تصویر زیر روبه‌رو خواهید شد.

نتیجه نهایی بخش submit اطلاعات

با بررسی و پیش بردن مراحل بالا شما توانایی ایجاد یک کامپوننت با قابلیت نمایش داده‌های ثبت شده را دارید. مرحله نخست طراحی سایت نظرسنجی با انگولار 2 که مشابه سایت reddit است، به اتمام رسید. حال شما باید قسمت دوم که با رنگ سبز مشخص شده بود را تکمیل کنید. این قسمت نیاز به توضیحات بیشتری دارد که در بخش ۱-۵ به تفصیل مورد بررسی قرار می‌گیرد.

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

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

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


فصل ۱

فصل ۲

فصل ۳

فصل ۴

فصل ۵

فصل ۶

نویسنده شوید

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

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

Morteza
26 تیر 1396
سلام ممنون ازتون برای آموزش خوب و کاملتون angular2_reddit قابل قبول نیست ظاهرا شاید بخاطر تغییرات اخیر اینطوری شده و به ـ گیر میده که باید - باشه

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

نام *
30 اسفند 1395
سلام و تشکر فراوان لطفا نحوه اضافه کردن فریم ورک bootstrap رو به ‍برنامه های angular2 بگید من از روش زیر رفتم ۱---------- npm install ng2-bootstrap bootstrap --save ۲---------- تغییر تو فایل .angular-cli.json "styles": [ "styles.css", "../node_modules/bootstrap/dist/css/bootstrap.min.css" ], ۳-------- تغییر src/app/app.module.ts import { AlertModule } from 'ng2-bootstrap'; ... @NgModule({ ... imports: [AlertModule.forRoot(), ... ], ... }) همه چیز اکی شد ولی خروجی قشنگی نگرفتم

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

روکسو
01 فروردین 1396
سلام وقت شما بخیر دوست عزیز ضمن عرض تبریک به مناسب فرا رسیدن سال ۱۳۹۶، برای اضافه کردن فریم ورک بوت استراپ به انگولار ۲ کافیست که فایل های فریم ورک بوت استراپ را به فایل index.html در پوشه‌ی src ضمیمه کنید. یعنی با استفاده از تگ های متا اونو به header قالب اصلی و مادر خودتون اضافه کنید.

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

صنم
18 تیر 1396
اینکارو کردم، اما استایل اعمال نشد

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

روکسو
19 تیر 1396
برای اینکار کافیه شما فایل BootStrap رو دانلود کنید و سپس داخل تگ های style یا script داخل فایل خودتون اضافه کنید. بهتره برای اینکار نحوه ی فراخوانی فایل های css و js رو مطالعه بفرمایید.

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