Angular 4.0從入門到實戰

AngularJS

優勢

  • 模板功能強大豐富,而且是聲明式的,自帶了豐富的Angular指令;
  • 是一個比較完善的前端MVC框架,包含模板,數據雙向綁定,路由,模塊化,服務,過濾器,依賴注入等全部功能;
  • 自定義Directive,比jQuery插件還靈活,可是須要深刻了解Directive的一些特性,簡單的封裝容易,複雜一點官方沒有提供詳細的介紹文檔,咱們能夠經過閱讀源代碼來找到某些咱們須要的東西,如:在directive使用 $parse;
  • ng模塊化比較大膽的引入了Java的一些東西(依賴注入),可以很容易的寫出可複用的代碼,對於敏捷開發的團隊來講很是有幫助
  • 補充:Angular支持單元測試和e2e-testing。

缺點

  • 雙向數據綁過多時,會影響性能(緣由:https://github.com/atian25/blog/issues/5
  • ngView路由只能有一個,不能嵌套多個視圖,雖然有 angular-ui/ui-router · GitHub 解決,可是貌似ui-router 對於URL的控制不是很靈活,必須是嵌套式的,第三方模塊;
  • 做用域把Ag的執行環境和瀏覽器環境隔離開,原生事件影響不了Ag的做用域
  • ng提倡在控制器裏面不要有操做DOM的代碼,對於一些jQuery 插件的使用,若是想不破壞代碼的整潔性,須要寫一些directive去封裝插件,可是如今有不少插件的版本已經支持Angular了,如:jQuery File Upload Demo
  • Angular 太笨重了,沒有讓用戶選擇一個輕量級的版本,固然1.2.X後,Angular也在作一些更改,好比把route,animate等模塊獨立出去,讓用戶本身去選擇。

架構

這裏寫圖片描述

Angular4.0

核心:組件css

問題改進

  • 默認綁定改成單向數據綁定
  • TypeScript 2.1 和 2.2 的兼容Angular已更新爲更新版本的TypeScript,提升了ngc的速度,而且有更好的類型檢查機制。
  • $scope不復存在
  • 表單驗證
  • TypeScript 2.1 和 2.2 的兼容Angular已更新爲更新版本的TypeScript,提升了ngc的速度,而且有更好的類型檢查機制。

新增特性

  • 命令行工具 AngularCLI
  • 服務端渲染(Angular Universal)
    • 加載速度
    • SEO(單頁應用對搜索引擎有很大的限制)
  • 移動和桌面兼容

架構

這裏寫圖片描述

其餘前端框架

React->UI組件(V)
- React,虛擬DOM,更新DOM次數少,內容也少。速度快
- FlUX架構(UI組件化和數據單向更新)
- 服務器渲染(預渲染應用發送客戶端,爬蟲依賴服務器的響應)
Vue->雨溪大牛我的主導,只關注WEB,服務器渲染(缺點)
- 簡單
- 靈活
- 性能html

Ag4開發環境搭建

Amber Cli(模塊的構建) -> Angular CLI <- Webpack(打包)
- Angular CLI (2以上的構建工具)
- npm install -g @angular/cli (安裝)
- ng version
- ng new 項目名字 –skip-install(網絡很差1)
- cnpm install(網絡很差2)
- 編譯,開發同步 np serve
- 測試打包 test build前端

安裝報錯
 constructor(_configPath, schema, configJson, fallbacks = []) { 重裝 npm uninstall -g angular-cli npm cache clean 
C:\Users\null\AppData\Roaming\npm\node_modules\@angular\cli\models\config\config
.js:17
    constructor(_configPath, schema, configJson, fallbacks = []) {
                                                           ^

SyntaxError: Unexpected token =
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:373:25)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
    at Object.<anonymous> (C:\Users\null\AppData\Roaming\npm\node_modules\@angul
ar\cli\models\config.js:3:18)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions..js (module.js:416:10)

升級Node version 6.x or higher
Linux node

npm install -g n
n stable

window直接替換就好了react

運行報錯
The "@angular/compiler-cli" package was not properly installed.
  1. Global package:
    rm -rf node_modules dist
    npm uninstall -g @angular/cli
    npm cache clean
  2. Reinstall and play (global)
    npm install -g @angular/cli@latest
    npm install
    ng serve
    https://stackoverflow.com/questions/42925690/angular2-cli-error-angular-compiler-cli-package-was-not-properly-installed/43021209
  • .editorconfig webstrom配置文件
  • karma.conf.js 自動化單元測試配置文件
  • protractor.conf.js 自動化單元測試
  • tslint 代碼規範監測
  • src
    • app 應用的組件和模塊
      • 模塊
      • 組件
    • assets 靜態資源
    • environments 環境配置 (多環境,開發,測試,生產)
    • index 根文件
    • main.ts 腳本執行的入口點(啓動項目)
    • polyfills 導入一些必要的庫,支持老版本的ag
    • css 全局樣式
    • test 自動化測試
    • tsconfig TypeScript編譯器

@Component**組件元數據裝飾器**可讓開發者經過Angular 的Component建立一個相似Java的class,並同時提供額外的元數據用於定義在運行環境中,根據元數據的值來渲染組件,這個component將如何運行/實例化以及被使用。
Template 定義組件的外觀
Controller包含組件的全部屬性和方法,頁面邏輯,處理模板上發生的事件git

這裏寫圖片描述

@NgModuleangularjs

  • declarations:只能聲明組件,指令,管道
  • imports 依賴模塊
    • Browser瀏覽器模塊
    • Form表單模塊
    • Http模塊
      • provides 模塊提供了什麼服務
      • bootstrap 模塊主組件

angular啓動過程

angular-cli.json
- 啓動加載頁面 index.html
- 啓動加載腳本 main.ts
- 腳本的工做 導入依賴模塊,主模塊app.module.ts,主模塊的依賴模塊…….在index.html尋找啓動模塊的主組件對應的css選擇器github

這裏寫圖片描述

Angular Route

這裏寫圖片描述

路由 - 分配特定的Url - 單頁應用(Simple Page App)

這裏寫圖片描述

利用url分配視圖狀態
- 子路由
- 保護路由
- 輔助路由web

ctrl + 1 導入component
ng new project routing 生成一個路由模塊express

app-routing.modul.ts路由配置,不用/開頭
const routes : Routes = [
{path:'',component:IndexComponent },
......
]

第一種:
路由使用,使用數組是要解決增長傳參的問題,字符串不方便
<a [routerLink] = "['/']" > 主頁 </a>
第二種:
<input type="button" value="主頁" (click)= "toIndex()" 事件綁定

控制器中定義
export class AppComponent {
    constructor(private router: Router){}

    toIndex(){
        this.router.navigate(['/']);

    }


}
404組件,通配符定義 **解決輸入未定義路徑報錯的狀況**
{path:'**',component:404Component },

404組件頁要放在最後,由於Ag路由使用先配置,先匹配的原則。

路由傳遞數據

查詢參數傳遞參數
/product?id=1&name=2    => ActiveRoute.queryParams[id]

路由路徑傳遞參數
{path:/product/:id} => /product/1   =>  ActivatedRoute.params[id]

路由配置傳遞參數
{path:/product,component: ProductComponent,data:[{isProd:yrue}]}
=>  ActivatedRoute.ata[0][isProd]
查詢傳遞參數

<a [routerLink] = "['/product']" [queryParams]="{id : 1}" > 主頁 </a>

子組件:接收參數
這裏寫圖片描述

自組件html:
{{ productId }}

路由傳遞參數

定義:
{path:product/:id」,component:ProductComponent },
html:

<a [routerLink] = "['/product',1]" > 主頁 </a>

子組件:prams 替換queryParams

問題:當咱們進行相同組件(參數不一樣)的路由切換時,沒法正常切換(不能切換)?
問題來源:組件只建立一次,建立時constructor,ngOnInit被調用
問題解決:參數快照(snapshot) -> 參數預約
這裏寫圖片描述

重定向路由

這裏寫圖片描述

這裏寫圖片描述

子路由

這裏寫圖片描述

生成子組件=>定義模板內容=>接收路由參數=>添加子組件=>添加子組件鏈接

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

輔助路由(全部頁面都顯示的組件)

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

主路由(組件只在主路由顯示):
outlets:{primary:'home',aux:"chat"}

路由守衛

這裏寫圖片描述

這裏寫圖片描述

經過返回的布爾值判斷執行動做。

這裏寫圖片描述

注意CanDeactivate多了一個泛型,也就是要聲明一下要保護的組件

這裏寫圖片描述

這裏寫圖片描述

Resolve守衛要解決的問題就是當咱們發送一個HTTP請求,要求路由切換時,請求是有延遲的,模板上的{{數據}}不能及時顯現出來。能夠在進入路由以前讀取數據,馬上顯現數據(略)

依賴注入(Dependency Injection)

在調用一個類的時候,先要實例化這個類,生成一個對象。
問題:寫一個類,過程當中要調用到不少其它類,甚至這裏的其它類,也要「依賴」於更多其它的類。手工實例化過於頻繁,臃腫。
依賴注入,全稱是「依賴注入到容器」, 容器(IOC容器)是一個設計模式,它也是個對象,你把某個類(無論有多少依賴關係)放入這個容器中,能夠「解析」出這個類的實例。
因此依賴注入就是把有依賴關係的類放入容器(IOC容器)中,而後解析出這個類的實例。

控制反轉(Inversion of Control)

代碼控制權從代碼內部轉到代碼外部
在Java開發中,Ioc意味着將你設計好的對象交給容器控制,而不是傳統的在你的對象內部直接控制。
傳統應用程序是由咱們本身在對象中主動控制去直接獲取依賴對象,也就是正轉;而反轉則是由容器來幫忙建立及注入依賴對象;爲什麼是反轉?由於由容器幫咱們查找及注入依賴對象,對象只是被動的接受依賴對象,因此是反轉;哪些方面反轉了?依賴對象的獲取被反轉了。

Angular 注入點只有一個,構造函數

這裏寫圖片描述

這裏寫圖片描述

好處:

  • 解耦和
  • 提升可測試性(建立簡單硬編碼測試組件)

這裏寫圖片描述

這裏寫圖片描述

當咱們須要重用ProductComponent,並且還須要另外一個productService類時

這裏寫圖片描述

這裏寫圖片描述

實例:

ng g component product1
ng g service shared/product

這裏寫圖片描述

@Injetable()裝飾器:把其餘服務注入該服務中。將該服務是否能注入其餘模塊是根據其做用域判斷的

提供器聲明在模塊中

這裏寫圖片描述

這裏寫圖片描述

綁定到模板

這裏寫圖片描述

擁有相同的Token,可是擁有不一樣的類
提供器做用域:聲明在組件中

ng g component product2
ng g service shared/anotherProduct

這裏寫圖片描述

引入控制器:

這裏寫圖片描述

綁定到模板

這裏寫圖片描述

工廠方法和值聲明提供器

聲明提供器,簡單的new一下。
遇到問題:服務對象須要根據條件來決定具體實例化哪一個對象,或者實例化對象,也就是調用構造函數時須要傳遞參數

工廠方法建立的對象是單例對象

這裏寫圖片描述

問題:方法內部實例化方法,該方法和服務對象緊密的耦合在了一塊兒

這裏寫圖片描述

問題:用具體值,變量來實現其依賴注入

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

手工使用注入器(避免使用,錯誤風格)

這裏寫圖片描述

數據綁定

容許將組件控制器的屬性,方法與組件的模板鏈接起來

Ag4默認改成單向數據綁定。
Ag1使用雙向(性能問題),在頁面維護一個存有全部表達式的列表,事件發生,反覆遍歷列表,確認數據是否徹底同步,耗性能
組件控制器的屬性和方法與組件的模板鏈接

這裏寫圖片描述

事件綁定

事件能夠是函數調用,屬性賦值,DOM事件,自定義事件

這裏寫圖片描述

屬性綁定

差值表達式至關於屬性綁定

控制器: private imgUrl:String="http://placehold.it/320x150"; 模板: <img [src]="imgUrl"> <img src="{{imgUrl}}"> 插值

event.target.value DOM屬性
event.target.getAttribute(‘value’) HTML
DOM屬性隨着輸入的改變而改變(指定當前值),HTML屬性不變(指定初始值,初始化DOM值,任務完成)
還有一個,input的disabled的值的改變沒法改變disabled的設置(true,false),可是DOM的設置是有效的

<input value="unchanging" (input)="doOnInput($event)"

這裏寫圖片描述

這裏寫圖片描述
這裏寫圖片描述

這裏寫圖片描述

HTML屬性綁定

當沒有DOM屬性綁定時,就使用html屬性綁定,好比td

這裏寫圖片描述

雙向綁定

主要使用表單from在

{(ngModel)} = ""

響應式編程(集成Rx系列)

管道:格式化模板輸出的一種可重用對象 |

{{birthday | date:'yyyy-MM-dd HH:mm:ss' | }} {{name | number:'2.1-4' | }} 整數幾位+小數最少幾位+小數最多幾位 {{name | async}}

自定義管道

ng g pipe pipe/multiple {{size | multiple}}

這裏寫圖片描述

組件間通訊

組件的輸入輸出屬性

  • 方法一:@Input() 輸入屬性經過屬性傳遞數據
    • 只能在有父子關係的組件中,由父組件傳遞給子組件
  • 方法二:路由參數輸入屬性,構造函數
  • @Output() 子組件向父組件傳遞數據
    • EventEmitter<泛型>輸出屬性
    • 捕捉EventEmitter和捕捉原生DOM的事件是同樣的,事件綁定
    • 雙向數據綁定 輸出屬性的名字 = 輸入屬性的名字 + Change

中間人模式傳遞數據

組件生命週期以及angular的變化發現機制

紅色方法調用一次,綠色方法調用屢次.共九個方法
接口對JS或者TS開發者可選,最好添加,優勢:IDE的支持和強類型的檢查

這裏寫圖片描述

  • ngOnChanges是當一個父組件修改或者初始化一個子組件的輸入屬性的時候被調用的。若是沒有輸入屬性,ngOnChanges永遠不會被調用
  • ngOnChanges首次調用必定發生在ngOnInit以前

小知識:

  • 父子組件之間應該避免直接訪問彼此的內部,而應該經過輸入輸出屬性來通信
  • 組件能夠經過輸出屬性發射自定義事件,這些事件能夠攜帶任何你想攜帶的數據
  • 在沒有父子關係的組件之間,儘可能使用中間人模式通訊
  • 父組件能夠在運行時投影一個或者多個模板片斷到子組件中
  • 每一個ag組件都提供了一組生命週期鉤子,供你在某些特定的事件中發生時執行相應的邏輯
  • ag的變動檢測機制會監控組件屬性的變化並自動更新視圖,這個檢測很是頻繁,並且默認是針對整個組件樹的,因此實現相關鉤子時要謹慎
  • 能夠標記你的組件樹中的一個分支,使其被排除在變動檢測機制以外

表單處理

純html表單:顯示錶單項,校驗用戶輸入(required,pattern 驗證消息過於模糊,消失時間過快,樣式不能修改),提交表單數據(較好的應該是提交數據以前,調用數據處理方法,校驗數據合法性,並且還能指定數據提交方法(異步,wobsocket,http)),不能知足特定需求,不夠靈活。

這裏寫圖片描述

這裏寫圖片描述

模板式表單FormsModule(快速)

  • 模板式表單FormsModule
  • 只能在模板中操做數據模型,不能在代碼中操做
  • 不能訪問數據模型相關的類,不能拿到類的引用,只能拿到數據,經過模板中給定的變量操做數據
    • NgForm 自動添加該指令,接管Form指令
      • 隱式建立一個FormGroup類的實例,FormGroup類用來存儲數據模型和表單數據
      • 自動發現NgModel的全部子元素,並自動將其添加到表單數據模型中
      • 也能夠綁定到其餘標籤上
      • 若是想使用原生Form,能夠在標籤添加ngNoForm屬性
      • NgForm能夠被模板本地變量引用,以便在模板中訪問NgForm對象的實例
      • 使用ngSubmit代替submit按鈕,阻止跳轉
    • NgModel 雙向數據綁定,標記一個html元素成爲表單的一部分
      • 隱式建立一個FormControl類的實例,利用FormControl來存儲數據的值
    • NgModelGroup
      • 表明表單的一部分,容許將表單字段組織在一塊兒,造成更清晰的層次關係
      • 隱式建立FromGroup的實例

這裏寫圖片描述

響應式表單 ReactiveFormsModule(可適配多個渲染器)

  • 響應式表單 ReactiveFormsModule
  • 能夠直接訪問數據模型相關的類,可是因爲不可引用, 只能在代碼中操做數據模型,不能在模板中操做
  • 第一步:建立數據模型,用來保存表單數據的數據結構
    • FormControl
    • FromGroup
      • 通常用來表明整個表單,或者表單字段固定的子集
      • 若是其中一個FromControl是無效的,那麼整個Fo’r’mGroup就是i無效的
    • FrormArray
      • 通常用來表明能夠增加的字段集合
      • 相似FromGroup,可是有一個長度屬性
      • 沒有key,只能經過序號訪問相關的元素
  • 第二部:使用指令將html鏈接到數據模型
  • 表單驗證

這裏寫圖片描述

與服務器通訊(http,socket)

npm init -y 引入帶有默認配置的package。j'son
npm i @types/node -save
  • Http 服務,它來自HttpModule,只有在調用subscribe時才發送請求
  • Websocket協議,更簡潔高效,並且時雙向的
  • 定義一個流須要定義三件事
    • 何時發射下一個元素
    • 何時拋異常
    • 何時發射流結束的信號

這裏寫圖片描述

構建(編譯和合並) 部署

構建
ng build  -> dist 
部署
添加新的部署策略 如圖 Ha'shLocationStrategy 解決構建後沒法跳轉路由的問題  url中出現了一個#號

這裏寫圖片描述

多壞境

ng serve ng build + 環境參數 啓動參數添加 --env=prod 生產環境 環境文件裏面能夠生成任意的文件屬性,能夠去引用