angular紅紅火火不少年了,一眨眼ng4都出來了,我也只能嘆息前端的突飛猛進,以及感嘆本身永遠追趕不上時代的步伐,可是不要緊,一個優秀的前端不在於他懂的無數的框架,而在於遇到問題時候懂得如何學習,如何解決,因此當你須要用到一個新技術的時候,你能夠很快的上手,如何學習,就很是重要,學習的途經有不少,每一個人都有本身的方法。因此良好的學習能力比你蜻蜓點水的瞭解重要得多,固然爲了求職,蜻蜓點水很重要,但對於職業生涯顯得沒那麼重要,騷年,好好培養本身的學習能力吧,有朝一日一定大有用途。html
廢話很少了,我一直用的是ng1.5版本,公司也沒要求要用其餘的,可是我一個大學同窗最近公司用了ng2作項目,遇到了問題,問我,聽他隨口一說,感受說ng2和ng1差異很大,其實核心的思想是同樣的,只不過把依賴注入設計更加嚴謹,模塊的概念更加清晰了。我推薦用angular-cli來搭建前端框架。前端
1.電腦環境node
首先須要你的電腦有node環境,建議高版本node,我用的是node7.×,還有npm 包管理工具,你安裝了node都會默認安裝npm的。git
2.安裝angular-cligithub
npm install -g @angular/cli
<1>.構建ng項目ajax
ng new my-app
應用代碼位於src文件夾中。 全部的Angular組件、模板、樣式、圖片以及你的應用所需的任何東西都在那裏。 這個文件夾以外的文件都是爲構建應用提供支持用的。npm
<2>.運行ng項目bootstrap
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,歡迎批評指正。