angular2框架搭建,angular-cli使用,angular2學習


  angular紅紅火火很多年了,一眨眼ng4都出來了,我也只能嘆息前端的日新月異,以及感嘆自己永遠追趕不上時代的步伐,但是沒關系,一個優秀的前端不在於他懂的無數的框架,而在於遇到問題時候懂得如何學習,如何解決,所以當你需要用到一個新技術的時候,你可以很快的上手,如何學習,就非常重要,學習的途經有很多,每個人都有自己的方法。所以良好的學習能力比你走馬觀花的了解重要得多,當然為了求職,走馬觀花很重要,但對於職業生涯顯得沒那么重要,騷年,好好培養自己的學習能力吧,有朝一日必定大有用途。

  廢話不多了,我一直用的是ng1.5版本,公司也沒要求要用其他的,但是我一個大學同學最近公司用了ng2做項目,遇到了問題,問我,聽他隨口一說,感覺說ng2和ng1差別很大,其實核心的思想是一樣的,只不過把依賴注入設計更加嚴謹,模塊的概念更加清晰了。我推薦用angular-cli來搭建前端框架。

  1.電腦環境

  首先需要你的電腦有node環境,建議高版本node,我用的是node7.×,還有npm 包管理工具,你安裝了node都會默認安裝npm的。

  2.安裝angular-cli

npm install -g @angular/cli

  <1>.構建ng項目

ng new my-app

  應用代碼位於src文件夾中。 所有的Angular組件、模板、樣式、圖片以及你的應用所需的任何東西都在那里。 這個文件夾之外的文件都是為構建應用提供支持用的。

  <2>.運行ng項目

cd my-app
ng serve 或者  npm start

  3.angular的模塊化結構

  在你的src文件夾內部的app文件夾中,你可以看到一系列文件,其中app.module.ts是這個項目的根模塊,每個項目都有一個根模塊,我們習慣命名為AppModule,這個稱之為項目的大腦,是項目的總指揮,所以在這個模塊中不能依賴過多的東西,不要引入過多的東西,它就是整個項目的指揮中心。

NgModule是一個裝飾器函數,它接收一個用來描述模塊屬性的元數據對象。其中最重要的屬性是:

- declarations - 聲明本模塊中擁有的視圖類。 Angular 有三種視圖類:組件、指令和管道。
- exports - declarations 的子集,可用於其它模塊的組件模板。
- imports - 本模塊聲明的組件模板需要的類所在的其它模塊。
- providers - 服務的創建者,並加入到全局服務列表中,可用於應用任何部分。
- bootstrap - 指定應用的主視圖(稱為根組件),它是所有其它視圖的宿主。只有根模塊才能設置bootstrap屬性。

我們平時真正開發都是在特性模塊里面的,特性模塊就是一個內聚的代碼塊專注於某個應用領域、工作流或緊密相關的功能。特性模塊也有上述屬性,特性模塊的並不是全局,只是針對自己需要的。

  <1>創建shared模塊

  在這個示例的項目中,先創建一個shared模塊(ng g module shared可以直接創建整個文件夾),這個模塊用於一些共享的組件,指令,過濾器。例如,我們全局任何的模塊都可能需要表單驗證提示這個功能,那么就把它封裝成一個公用的組件,在shared.component.ts里面寫入:

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

@Component({
  selector: 'form-help',
  template: `<div *ngIf="target.invalid">
                <div  *ngIf="!target._parent.submitted && target.dirty && target.errors.required" class="alert alert-danger col-sm-6">賬號是必須輸入的11</div>
                <div  *ngIf="target._parent.submitted && target.errors.required" class="alert alert-danger col-sm-6">賬號是必須輸入的</div>
                <div *ngIf="target.dirty && target.errors.pattern" class="alert alert-danger col-sm-6">以字母開頭</div>
                <div *ngIf="target.dirty && target.errors.minlength" class="alert alert-danger col-sm-6">不能少於{{target.errors.minlength.requiredLength}}</div>
                <div *ngIf="target.dirty && target.errors.maxlength" class="alert alert-danger col-sm-6">不能大於{{target.errors.maxlength.requiredLength}}</div>
            </div>`
})
export class FormComponent {
   @Input() target
    constructor() {
    }
}

/*表單的驗證規則,最大長度,最小長度,是不是必須填,正則等一系列的判斷
*在這里target._parent.submitted指的就是整個表單,如果整個表單被提交過,則submitted為true,根據這個來讓沒有輸入過的表單顯示錯誤
*/

其中@input就是需要外部傳入內部的值。然后需要在SharedModule的declarations中聲明這個組件,才能起效果,如果是自己用則不需要在exports數組中聲明,但是我們這個是共享模塊,需要在任何其他的模塊中使用的,所以就需要在exports數組中聲明,表明這個組件可以被其他引入該模塊的文件共享。shared.module.ts文件代碼如下:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';

import { HighlightDirective } from './shared.directive'
import { InputChangeDirective } from './shared.directive'
import {FormComponent} from './shared.component'

@NgModule({
    imports: [//這個模塊需要的其他模塊就需要在此引入,ng2把非常多的功能都拆成模塊引入,比如ngModel這個指令存在FormsModule這個angular自帶模塊中,不引入就會報錯
        CommonModule,
        FormsModule
    ],
    declarations: [
        FormComponent
    ],
    providers: [ 
       
    ],
    exports:[FormComponent]
})
export class SharedModule { }

<2>.創建login模塊

然后我們創建我們的login模塊,登入模塊,登入模塊中組要用到上述模塊的驗證功能,所以在這個模塊的login.module.ts文件中需要提前引入這個shared模塊,代碼如下:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms'; 

import {LoginRouterModule} from './login.routing'
import {LoginComponent} from './login.component';

import {SharedModule} from '../shared/shared.module'//引入shared模塊
import {LoginService} from './login.service'

@NgModule({
    imports: [
        CommonModule,
        FormsModule,
        LoginRouterModule,
        SharedModule//聲明shared模塊
     
    ],
    declarations: [
        LoginComponent,
    ],
    providers: [LoginService]//這個是login模塊的服務,即這個模塊需要的ajax接口代碼
})
export class LoginModule { }

這個時候就可以使用shared模塊,但是angular2的驗證跟ng1也有點差別,先看login.component.ts中html代碼:

<div class="container">
    <form class="form-horizontal" role="form" name="myForm" #forma="ngForm">
        <div class="form-group">
            <label for="firstname" class="col-sm-2 control-label">名字</label>
            <div class="col-sm-10">
                <input type="text" class="form-control" autocomplete="off" id="firstname" name="name" placeholder="請輸入名字" [(ngModel)]='name' #ipt1="ngModel" minlength="3" required='true' pattern="^[a-z]+$" maxlength="6" />
                <form-help [target]='ipt1'></form-help>
            </div>
        </div>
        <div class="form-group">
          <label for="lastname" class="col-sm-2 control-label">姓</label>
          <div class="col-sm-10">
                <input type="text" class="form-control" autocomplete="off" id="lastname" name="psw" placeholder="請輸入姓" [(ngModel)]='psw' #ipt2="ngModel" required='true' minlength="5"/>
                <form-help [target]='ipt2'></form-help>
            </div>
        </div>
        <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
                <button type="button" class="btn btn-default" (click)="submit(forma)">登錄</button>
            </div>
        </div>
    </form>
</div>

文件中#forma="ngForm"表明這是個ng表單,每個input都需要驗證提示,則給input加上唯一的標識符#inp1=‘ngModel’,#inp2='ngModel'....,[(ngModel)]='psw'是數據雙向綁定,<form-help [target]='ipt2'></form-help>就是引用了shared模塊的,傳入數據給定義的target,則就講這個input的驗證信息傳到form-help這個組件內,會經過一系列的驗證告訴你提示信息。

<3>.創建全局創建一次的方法

看到這個大家肯定很模糊,前面提到shared的模塊式共享的模塊,在每個其他模塊都需要引入的,每次使用都是會創建實例的,但是一些全局的方法,比如ajax調用錯誤處理,刪除提示等全局的方法,我們只需要引入一次,其他時候直接調用方法即可,並不希望每次都要引入每個特性模塊。於是core模塊出現了,core.service.ts文件如下:

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

//封裝后台錯誤提示信息的右上角彈出紅色小框
import {ToasterService} from 'angular2-toastr';

//封裝一些刪除,彈出輸入框的確認操作
declare var swal:any;//在使用之前先聲明要用到(用的是sweetalert插件,使用前在index.html里面引入相應的js文件)


@Injectable()
export class CoreService {

    constructor(public _toaster: ToasterService) {}

    toasterError(title,message): void {  //標題    提示信息 顯示關閉按鈕 消失需要時間
        this._toaster.error(title, message, true, 2000);
    } 

    toasterSuccess(): void {
        this._toaster.success('title', 'message', true, 2000);
    }

    //確認刪除,刪除后的操作等,刪除失敗的處理等都需要后期的處理
    comfirmDelete(type):void {
        swal({
            title:"確定要刪除嗎?",
            text:'刪除吧',
            type:type,
            showCancelButton: true,
            confirmButtonColor: "#DD6B55",
            confirmButtonText: "確定!",
            cancelButtonText: "取消!",
            closeOnConfirm: false,
            closeOnCancel: true,
            showLoaderOnConfirm: true
        },function(isConfirm){
            if(isConfirm){
                setTimeout(function(){
                    swal({
                        title: "刪除成功!",
                        type: "success",
                        confirmButtonColor: "#007AFF"
                    });
                },1000)
                
            }
        })
    }
}

上述就是我舉得例子,一些公用的方法,不希望處處創建,也符合函數的功能,實現代碼的復用。當然要在該模塊的providers中聲明:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';


import {CoreComponent} from './core.component'
import {CoreService} from './core.service'

//以下兩個屬於angular2-toastr的東西
import {ToasterComponent, ToastComponent} from 'angular2-toastr/index'
import {ToasterService} from 'angular2-toastr';

@NgModule({
    imports: [
        CommonModule,
    ],
    declarations: [
        ToasterComponent,
        ToastComponent,
        CoreComponent
    ],
    providers: [ 
        ToasterService,//聲明服務
        CoreService
   ],
  exports:[]
})
export class CoreModule { }

但是說到底這還是core某塊中的,如何讓全局都可以使用呢,只要在根模塊下引入該模塊即可,app.module.ts代碼如下:

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 {LoginModule} from './login/login.module'
/*app路由*/
import {routing} from './app.routing'
/*共享模塊*/
import {CoreModule} from './core/core.module'
//notpage
import {NotPageComponent} from './notpage/notpage.component'
//ng2-bootstrap
import { AlertModule} from 'ng2-bootstrap';

@NgModule({
      declarations: [//可以告訴 Angular 哪個組件屬於AppModule ,指令和管道 — 它們也必須被添加到declarations數組
        AppComponent,
        NotPageComponent
      ],

      imports: [//imports數組中應該只有NgModule類。不要放置其它類型的類。
        BrowserModule,
        FormsModule,
        HttpModule,
        LoginModule,//初次加載的模塊,其他的模塊都是路由惰性加載的
        CoreModule,//這就是coreModule的聲明,可以使用這個模塊全局的方法
        routing,
      ],
      providers: [],//引入服務,在所有這個模塊下的都可以使用,不引入會報錯,如果只需要在某個component下面使用,則只需要在某個component里面的providers里面引用即可
      bootstrap: [AppComponent]
})

export class AppModule { }

4.路由

路由是每個框架必不可少的東西,我們期望的路由結構是這樣的,根模塊通過路由加載其他各特性模塊,然后特性模塊有自己的路由,引導去個特性模塊里面不同的頁面;為了方便演示,我在app下創建一個app.routing.ts文件,書寫引導去哥特性模塊的路由:

import {Routes, RouterModule} from '@angular/router';
import {NotPageComponent} from './notpage/notpage.component'

const routes: Routes = [
    { path: '', redirectTo: 'login', pathMatch: 'full' },//默認到的地方
    { path: 'home', loadChildren: './home/home.module#HomeModule' },
    { path:'class', loadChildren: './class/class.module#ClassModule'},
    { path: '**', component: NotPageComponent}
];
export const routing = RouterModule.forRoot(routes);

把這個routing在AppModule的imports中引入,每個特性模塊自己的路由也是這樣引入。這個默認的login模塊需要首先在AppModule中聲明,其他惰性加載的不需要;我們再看看home這個模塊的路由,在home.routing.ts中代碼如下:

import {Routes, RouterModule} from '@angular/router';
import {HomeComponent} from './home.component'
import {HomeModule1Component} from './home.module1.component'
import {HomeModule2Component} from './home.module2.component'

const tablesRoutes: Routes = [
    {
        path:'',//注意是'',並不是home
        component:HomeComponent,
        children: [
           { path: '', component: HomeModule1Component },
           { path: 'homemodule1', component: HomeModule1Component },
           { path: 'homemodule2', component: HomeModule2Component },
        ]
    }
]
export const homeRouting = RouterModule.forChild(tablesRoutes);

根據home,home/homemodule1,home/homemodule2加載home模塊的不同的頁面。

5.期待的頁面路由結構

在我們的根目錄的component.ts的html中我們並不需要太多的東西,只需要他提供一個視圖的窗口即可,如下:

 

<router-outlet></router-outlet>

 

在特性模塊例如home中,我們需要這個特性模塊的視圖窗口和導航,於是home.component.ts中的html文件如下:

<div class="row">
    <div class="col-sm-3">
        <ul class="nav nav-pills nav-stacked">
            <li><a routerLink="homemodule1" routerLinkActive="active">HomeModule1</a></li>
            <li><a routerLink="homemodule2" routerLinkActive="active">HomeModule2</a></li>
            <li><a routerLink="../class">Class</a></li>
            <li><a routerLink="home">VB.Net</a></li>
            <li><a routerLink="home">Java</a></li>
            <li><a routerLink="home">PHP</a></li>
        </ul>
    </div>
    <div class="col-sm-9">
        <router-outlet></router-outlet>//這個是本特性模塊的視圖
    </div>
</div>

6.總結

以上就是整個項目的框架搭建簡述,ng2遵循的規則就是,1.我需要的模塊就需要聲明;2.全局的方法寫在core模塊,只在根模塊引入;3.共享的模塊寫在shared模塊,並在每個用到的模塊中引入;其中源碼在個人github上:https://github.com/jiangzhenfei/ng2-fei-cli,歡迎批評指正。

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM