成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Angular 2.x 從0到1 (五)史上最簡(jiǎn)單的Angular2教程

dcr309duan / 766人閱讀

摘要:如果該構(gòu)造函數(shù)在我們所期望的中運(yùn)行,就沒有任何祖先注入器能夠提供的實(shí)例,于是注入器會(huì)放棄查找。但裝飾器表示找不到該服務(wù)也無(wú)所謂。用處理導(dǎo)航到子路由的情況。路由器會(huì)先按照從最深的子路由由下往上檢查的順序來(lái)檢查守護(hù)條件。

第一節(jié):Angular 2.0 從0到1 (一)
第二節(jié):Angular 2.0 從0到1 (二)
第三節(jié):Angular 2.0 從0到1 (三)
第四節(jié):Angular 2.0 從0到1 (四)
第五節(jié):Angular 2.0 從0到1 (五)

第五節(jié):多用戶版本的待辦事項(xiàng)應(yīng)用

第四節(jié)我們完成的Todo的基本功能看起來(lái)還不錯(cuò),但是有個(gè)大問(wèn)題,就是每個(gè)用戶看到的都是一樣的待辦事項(xiàng),我們希望的是每個(gè)用戶擁有自己的待辦事項(xiàng)列表。我們來(lái)分析一下怎么做,如果每個(gè)todo對(duì)象帶一個(gè)UserId屬性是不是可以解決呢?好像可以,邏輯大概是這樣:用戶登錄后轉(zhuǎn)到/todo,TodoComponent得到當(dāng)前用戶的UserId,然后調(diào)用TodoService中的方法,傳入當(dāng)前用戶的UserId,TodoService中按UserId去篩選當(dāng)前用戶的Todos。
但可惜我們目前的LoginComponent還是個(gè)實(shí)驗(yàn)品,很多功能的缺失,我們是先去做Login呢,還是利用現(xiàn)有的Todo對(duì)象先試驗(yàn)一下呢?我個(gè)人的習(xí)慣是先進(jìn)行試驗(yàn)。

數(shù)據(jù)驅(qū)動(dòng)開發(fā)

按之前我們分析的,給todo加一個(gè)userId屬性,我們手動(dòng)給我們目前的數(shù)據(jù)加上userId屬性吧。更改todo odo-data.json為下面的樣子:

{
  "todos": [
    {
      "id": "bf75769b-4810-64e9-d154-418ff2dbf55e",
      "desc": "getting up",
      "completed": false,
      "userId": 1
    },
    {
      "id": "5894a12f-dae1-5ab0-5761-1371ba4f703e",
      "desc": "have breakfast",
      "completed": true,
      "userId": 2
    },
    {
      "id": "0d2596c4-216b-df3d-1608-633899c5a549",
      "desc": "go to school",
      "completed": true,
      "userId": 1
    },
    {
      "id": "0b1f6614-1def-3346-f070-d6d39c02d6b7",
      "desc": "test",
      "completed": false,
      "userId": 2
    },
    {
      "id": "c1e02a43-6364-5515-1652-a772f0fab7b3",
      "desc": "This is a te",
      "completed": false,
      "userId": 1
    }
  ]
}

如果你還沒有啟動(dòng)json-server的話讓我們啟動(dòng)它: json-server ./src/app/todo/todo-data.json,然后打開瀏覽器在地址欄輸入http://localhost:3000/todos/?userId=2你會(huì)看到只有userId=2的json被輸出了

[
  {
    "id": "5894a12f-dae1-5ab0-5761-1371ba4f703e",
    "desc": "have breakfast",
    "completed": true,
    "userId": 2
  },
  {
    "id": "0b1f6614-1def-3346-f070-d6d39c02d6b7",
    "desc": "test",
    "completed": false,
    "userId": 2
  }
]

有興趣的話可以再試試http://localhost:3000/todos/?userId=2&completed=false或其他組合查詢?,F(xiàn)在todo有了userId字段,但我們還沒有User對(duì)象,User的json表現(xiàn)形式看起來(lái)應(yīng)該是這樣:

    {
      "id": 1,
      "username": "wang",
      "password": "1234"
    }

當(dāng)然這個(gè)表現(xiàn)形式有很多問(wèn)題,比如密碼是明文的,這些問(wèn)題我們先不管,但大概樣子是類似的。那么現(xiàn)在如果要建立User數(shù)據(jù)庫(kù)的話,我們應(yīng)該新建一個(gè)user-data.json

{
  "users": [
    {
      "id": 1,
      "username": "wang",
      "password": "1234"
    },
    {
      "id": 2,
      "username": "peng",
      "password": "5678"
    }
  ]
}

但這樣做的話感覺多帶帶為其建一個(gè)文件有點(diǎn)不值得,我們干脆把user和todo數(shù)據(jù)都放在一個(gè)文件吧,現(xiàn)在刪除./src/app/todo/todo-data.json刪除,在srcapp下面新建一個(gè)data.json

//srcappdata.json
{
  "todos": [
    {
      "id": "bf75769b-4810-64e9-d154-418ff2dbf55e",
      "desc": "getting up",
      "completed": false,
      "userId": 1
    },
    {
      "id": "5894a12f-dae1-5ab0-5761-1371ba4f703e",
      "desc": "have breakfast",
      "completed": true,
      "userId": 2
    },
    {
      "id": "0d2596c4-216b-df3d-1608-633899c5a549",
      "desc": "go to school",
      "completed": true,
      "userId": 1
    },
    {
      "id": "0b1f6614-1def-3346-f070-d6d39c02d6b7",
      "desc": "test",
      "completed": false,
      "userId": 2
    },
    {
      "id": "c1e02a43-6364-5515-1652-a772f0fab7b3",
      "desc": "This is a te",
      "completed": false,
      "userId": 1
    }
  ],
  "users": [
    {
      "id": 1,
      "username": "wang",
      "password": "1234"
    },
    {
      "id": 2,
      "username": "peng",
      "password": "5678"
    }
  ]
}

當(dāng)然有了數(shù)據(jù),我們就得有對(duì)應(yīng)的對(duì)象,基于同樣的理由,我們把所有的entity對(duì)象都放在一個(gè)文件:刪除srcapp odo odo.model.ts,在srcapp下新建一個(gè)目錄domain,然后在domain下新建一個(gè)entities.ts,請(qǐng)別忘了更新所有的引用。

export class Todo {
  id: string;
  desc: string;
  completed: boolean;
  userId: number;
}
export class User {
  id: number;
  username: string;
  password: string;
}
驗(yàn)證用戶賬戶的流程

我們來(lái)梳理一下用戶驗(yàn)證的流程

存儲(chǔ)要訪問(wèn)的URL

根據(jù)本地的已登錄標(biāo)識(shí)判斷是否此用戶已經(jīng)登錄,如果已登錄就直接放行

如果未登錄導(dǎo)航到登錄頁(yè)面 用戶填寫用戶名和密碼進(jìn)行登錄

系統(tǒng)根據(jù)用戶名查找用戶表中是否存在此用戶,如果不存在此用戶,返回錯(cuò)誤

如果存在對(duì)比填寫的密碼和存儲(chǔ)的密碼是否一致,如果不一致,返回錯(cuò)誤

如果一致,存儲(chǔ)此用戶的已登錄標(biāo)識(shí)到本地

導(dǎo)航到原本要訪問(wèn)的URL即第一步中存儲(chǔ)的URL,刪掉本地存儲(chǔ)的URL

看上去我們需要實(shí)現(xiàn)

UserService:用于通過(guò)用戶名查找用戶并返回用戶

AuthService:用于認(rèn)證用戶,其中需要利用UserService的方法

AuthGuard:路由攔截器,用于攔截到路由后通過(guò)AuthService來(lái)知道此用戶是否有權(quán)限訪問(wèn)該路由,根據(jù)結(jié)果導(dǎo)航到不同路徑。
看到這里,你可能有些疑問(wèn),為什么我們不把UserService和AuthService合并呢?這是因?yàn)閁serService是用于對(duì)用戶的操作的,不光認(rèn)證流程需要用到它,我們未來(lái)要實(shí)現(xiàn)的一系列功能都要用到它,比如注冊(cè)用戶,后臺(tái)用戶管理,以及主頁(yè)要顯示用戶名稱等。

核心模塊

根據(jù)這個(gè)邏輯流程,我們來(lái)組織一下代碼。開始之前我們想把認(rèn)證相關(guān)的代碼組織在一個(gè)新的模塊下,我們暫時(shí)叫它core吧。在srcapp下新建一個(gè)core目錄,然后在core下面新建一個(gè)core.module.ts

import { ModuleWithProviders, NgModule, Optional, SkipSelf } from "@angular/core";
import { CommonModule } from "@angular/common";
@NgModule({
  imports: [
    CommonModule
  ]
})
export class CoreModule {
  constructor (@Optional() @SkipSelf() parentModule: CoreModule) {
    if (parentModule) {
      throw new Error(
        "CoreModule is already loaded. Import it in the AppModule only");
    }
  }

注意到這個(gè)模塊和其他模塊不太一樣,原因是我們希望只在應(yīng)用啟動(dòng)時(shí)導(dǎo)入它一次,而不會(huì)在其它地方導(dǎo)入它。在模塊的構(gòu)造函數(shù)中我們會(huì)要求Angular把CoreModule注入自身,這看起來(lái)像一個(gè)危險(xiǎn)的循環(huán)注入。不過(guò),@SkipSelf裝飾器意味著在當(dāng)前注入器的所有祖先注入器中尋找CoreModule。如果該構(gòu)造函數(shù)在我們所期望的AppModule中運(yùn)行,就沒有任何祖先注入器能夠提供CoreModule的實(shí)例,于是注入器會(huì)放棄查找。默認(rèn)情況下,當(dāng)注入器找不到想找的提供商時(shí),會(huì)拋出一個(gè)錯(cuò)誤。 但@Optional裝飾器表示找不到該服務(wù)也無(wú)所謂。 于是注入器會(huì)返回null,parentModule參數(shù)也就被賦成了空值,而構(gòu)造函數(shù)沒有任何異常。
那么我們?cè)谑裁磿r(shí)候會(huì)需要這樣一個(gè)模塊?比如在這個(gè)模塊中我們可能會(huì)要提供用戶服務(wù)(UserService),這樣的服務(wù)系統(tǒng)各個(gè)地方都需要,但我們不希望它被創(chuàng)建多次,希望它是一個(gè)單例。再比如某些只應(yīng)用于AppComponent模板的一次性組件,沒有必要共享它們,然而如果把它們留在根目錄,還是顯得太亂了。我們可以通過(guò)這種形式隱藏它們的實(shí)現(xiàn)細(xì)節(jié)。然后通過(guò)根模塊AppModule導(dǎo)入CoreModule來(lái)獲取其能力。

路由守衛(wèi)

首先我們來(lái)看看Angular內(nèi)建的路由守衛(wèi)機(jī)制,在實(shí)際工作中我們常常會(huì)碰到下列需求:

該用戶可能無(wú)權(quán)導(dǎo)航到目標(biāo)組件。 導(dǎo)航前需要用戶先登錄(認(rèn)證)。

在顯示目標(biāo)組件前,我們可能得先獲取某些數(shù)據(jù)。

在離開組件前,我們可能要先保存修改。

我們可能要詢問(wèn)用戶:你是否要放棄本次更改,而不用保存它們?

我們可以往路由配置中添加守衛(wèi),來(lái)處理這些場(chǎng)景。守衛(wèi)返回true,導(dǎo)航過(guò)程會(huì)繼續(xù);返回false,導(dǎo)航過(guò)程會(huì)終止,且用戶會(huì)留在原地(守衛(wèi)還可以告訴路由器導(dǎo)航到別處,這樣也取消當(dāng)前的導(dǎo)航)。

路由器支持多種守衛(wèi):

用CanActivate來(lái)處理導(dǎo)航到某路由的情況。

用CanActivateChild處理導(dǎo)航到子路由的情況。

用CanDeactivate來(lái)處理從當(dāng)前路由離開的情況。

用Resolve在路由激活之前獲取路由數(shù)據(jù)。

用CanLoad來(lái)處理異步導(dǎo)航到某特性模塊的情況。

在分層路由的每個(gè)級(jí)別上,我們都可以設(shè)置多個(gè)守衛(wèi)。路由器會(huì)先按照從最深的子路由由下往上檢查的順序來(lái)檢查CanDeactivate守護(hù)條件。然后它會(huì)按照從上到下的順序檢查CanActivate守衛(wèi)。如果任何守衛(wèi)返回false,其它尚未完成的守衛(wèi)會(huì)被取消,這樣整個(gè)導(dǎo)航就被取消了。

本例中我們希望用戶未登錄前不能訪問(wèn)todo,那么需要使用CanActivate

import { AuthGuardService } from "../core/auth-guard.service";
const routes: Routes = [
  {
    path: "todo/:filter",
    canActivate: [AuthGuardService],
    component: TodoComponent
  }
];

當(dāng)然光這么寫是沒有用的,下面我們來(lái)建立一個(gè)AuthGuardService,命令行中鍵入ng g s core/auth-guard(angular-cli對(duì)于Camel寫法的文件名是采用-來(lái)分隔每個(gè)大寫的詞)。

import { Injectable, Inject } from "@angular/core";
import {
  CanActivate,
  Router,
  ActivatedRouteSnapshot,
  RouterStateSnapshot }    from "@angular/router";

@Injectable()
export class AuthGuardService implements CanActivate {

  constructor(private router: Router) { }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    //取得用戶訪問(wèn)的URL
    let url: string = state.url;
    return this.checkLogin(url);
  }
  checkLogin(url: string): boolean {
    //如果用戶已經(jīng)登錄就放行
    if (localStorage.getItem("userId") !== null) { return true; }
    //否則,存儲(chǔ)要訪問(wèn)的URl到本地
    localStorage.setItem("redirectUrl", url);
    //然后導(dǎo)航到登陸頁(yè)面
    this.router.navigate(["/login"]);
    //返回false,取消導(dǎo)航
    return false;
  }
}

觀察上面代碼,我們發(fā)現(xiàn)本地存儲(chǔ)的userId的存在與否決定了用戶是否已登錄的狀態(tài),這當(dāng)然是一個(gè)漏洞百出的實(shí)現(xiàn),但我們暫且不去管它?,F(xiàn)在我們要在登錄時(shí)把這個(gè)狀態(tài)值寫進(jìn)去。我們新建一個(gè)登錄鑒權(quán)的AuthServiceng g s core/auth

import { Injectable, Inject } from "@angular/core";
import { Http, Headers, Response } from "@angular/http";

import "rxjs/add/operator/toPromise";
import { Auth } from "../domain/entities";

@Injectable()
export class AuthService {

  constructor(private http: Http, @Inject("user") private userService) { }

  loginWithCredentials(username: string, password: string): Promise {
    return this.userService
      .findUser(username)
      .then(user => {
        let auth = new Auth();
        localStorage.removeItem("userId");
        let redirectUrl = (localStorage.getItem("redirectUrl") === null)?
          "/": localStorage.getItem("redirectUrl");
        auth.redirectUrl = redirectUrl;
        if (null === user){
          auth.hasError = true;
          auth.errMsg = "user not found";
        } else if (password === user.password) {
          auth.user = Object.assign({}, user);
          auth.hasError = false;
          localStorage.setItem("userId",user.id);
        } else {
          auth.hasError = true;
          auth.errMsg = "password not match";
        }

        return auth;
      })
      .catch(this.handleError);
  }
  private handleError(error: any): Promise {
    console.error("An error occurred", error); // for demo purposes only
    return Promise.reject(error.message || error);
  }
}

注意到我們返回了一個(gè)Auth對(duì)象,這是因?yàn)槲覀円缼准拢?/p>

用戶最初要導(dǎo)航的頁(yè)面URL

用戶對(duì)象

如果發(fā)生錯(cuò)誤的話,是什么錯(cuò)誤,我們需要反饋給用戶

這個(gè)Auth對(duì)象同樣在srcappdomainentities.ts中聲明

export class Auth {
  user: User;
  hasError: boolean;
  errMsg: string;
  redirectUrl: string;
}

當(dāng)然我們還得實(shí)現(xiàn)UserService:ng g s user

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

import { Http, Headers, Response } from "@angular/http";

import "rxjs/add/operator/toPromise";
import { User } from "../domain/entities";

@Injectable()
export class UserService {

  private api_url = "http://localhost:3000/users";

  constructor(private http: Http) { }

  findUser(username: string): Promise {
    const url = `${this.api_url}/?username=${username}`;
    return this.http.get(url)
              .toPromise()
              .then(res => {
                let users = res.json() as User[];
                return (users.length>0)?users[0]:null;
              })
              .catch(this.handleError);
  }
  private handleError(error: any): Promise {
    console.error("An error occurred", error); // for demo purposes only
    return Promise.reject(error.message || error);
  }
}

這段代碼比較簡(jiǎn)單,就不細(xì)講了。下面我們改造一下srcapploginlogin.component.html,在原來(lái)用戶名的驗(yàn)證信息下加入,用于顯示用戶不存在或者密碼不對(duì)的情況

        
this is required
should be at least 3 charactors
{{auth.errMsg}}

當(dāng)然我們還得改造srcapploginlogin.component.ts

import { Component, OnInit, Inject } from "@angular/core";
import { Router, ActivatedRoute, Params } from "@angular/router";

import { Auth } from "../domain/entities";

@Component({
  selector: "app-login",
  templateUrl: "./login.component.html",
  styleUrls: ["./login.component.css"]
})
export class LoginComponent implements OnInit {

  username = "";
  password = "";
  auth: Auth;

  constructor(@Inject("auth") private service, private router: Router) { }

  ngOnInit() {
  }

  onSubmit(formValue){
    this.service
      .loginWithCredentials(formValue.login.username, formValue.login.password)
      .then(auth => {
        let redirectUrl = (auth.redirectUrl === null)? "/": auth.redirectUrl;
        if(!auth.hasError){
          this.router.navigate([redirectUrl]);
          localStorage.removeItem("redirectUrl");
        } else {
          this.auth = Object.assign({}, auth);
        }
      });
  }
}

然后我們別忘了在core模塊中聲明我們的服務(wù)srcappcorecore.module.ts

import { ModuleWithProviders, NgModule, Optional, SkipSelf } from "@angular/core";
import { CommonModule } from "@angular/common";
import { AuthService } from "./auth.service";
import { UserService } from "./user.service";
import { AuthGuardService } from "./auth-guard.service";
@NgModule({
  imports: [
    CommonModule
  ],
  providers: [
    { provide: "auth", useClass: AuthService },
    { provide: "user", useClass: UserService },
    AuthGuardService
    ]
})
export class CoreModule {
  constructor (@Optional() @SkipSelf() parentModule: CoreModule) {
    if (parentModule) {
      throw new Error(
        "CoreModule is already loaded. Import it in the AppModule only");
    }
  }
}

最后我們得改寫一下TodoService,因?yàn)槲覀冊(cè)L問(wèn)的URL變了,要傳遞的數(shù)據(jù)也有些變化

//todo.service.ts代碼片段
  // POST /todos
  addTodo(desc:string): Promise {
    //“+”是一個(gè)簡(jiǎn)易方法可以把string轉(zhuǎn)成number
    const userId:number = +localStorage.getItem("userId");
    let todo = {
      id: UUID.UUID(),
      desc: desc,
      completed: false,
      userId
    };
    return this.http
            .post(this.api_url, JSON.stringify(todo), {headers: this.headers})
            .toPromise()
            .then(res => res.json() as Todo)
            .catch(this.handleError);
  }
  // GET /todos
  getTodos(): Promise{
    const userId = +localStorage.getItem("userId");
    const url = `${this.api_url}/?userId=${userId}`;
    return this.http.get(url)
              .toPromise()
              .then(res => res.json() as Todo[])
              .catch(this.handleError);
  }

  // GET /todos?completed=true/false
  filterTodos(filter: string): Promise {
    const userId:number = +localStorage.getItem("userId");
    const url = `${this.api_url}/?userId=${userId}`;
    switch(filter){
      case "ACTIVE": return this.http
                        .get(`${url}&completed=false`)
                        .toPromise()
                        .then(res => res.json() as Todo[])
                        .catch(this.handleError);
      case "COMPLETED": return this.http
                          .get(`${url}&completed=true`)
                          .toPromise()
                          .then(res => res.json() as Todo[])
                          .catch(this.handleError);
      default:
        return this.getTodos();
    }
  }

現(xiàn)在應(yīng)該已經(jīng)ok了,我們來(lái)看看效果:
用戶密碼不匹配時(shí),顯示password not match

用戶不存在時(shí),顯示user not found

直接在瀏覽器地址欄輸入http://localhost:4200/todo,你會(huì)發(fā)現(xiàn)被重新導(dǎo)航到了login。輸入正確的用戶名密碼后,我們被導(dǎo)航到了todo,現(xiàn)在每個(gè)用戶都可以創(chuàng)建屬于自己的待辦事項(xiàng)了。

路由模塊化

Angular團(tuán)隊(duì)推薦把路由模塊化,這樣便于使業(yè)務(wù)邏輯和路由松耦合。雖然目前在我們的應(yīng)用中感覺用處不大,但按官方推薦的方式還是和大家一起改造一下吧。刪掉原有的app.routes.tstodo.routes.ts。添加app-routing.module.ts:

import { NgModule }     from "@angular/core";
import { Routes, RouterModule } from "@angular/router";
import { LoginComponent } from "./login/login.component";

const routes: Routes = [
  {
    path: "",
    redirectTo: "login",
    pathMatch: "full"
  },
  {
    path: "login",
    component: LoginComponent
  },
  {
    path: "todo",
    redirectTo: "todo/ALL"
  }
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes)
  ],
  exports: [
    RouterModule
  ]
})
export class AppRoutingModule {}

以及srcapp odo odo-routing.module.ts

import { NgModule } from "@angular/core";
import { Routes, RouterModule } from "@angular/router";
import { TodoComponent } from "./todo.component";

import { AuthGuardService } from "../core/auth-guard.service";

const routes: Routes = [
  {
    path: "todo/:filter",
    canActivate: [AuthGuardService],
    component: TodoComponent
  }
];

@NgModule({
  imports: [ RouterModule.forChild(routes) ],
  exports: [ RouterModule ]
})
export class TodoRoutingModule { }

并分別在AppModule和TodoModule中引入路由模塊。

用VSCode進(jìn)行調(diào)試

有讀者問(wèn)如何用vscode進(jìn)行debug,這章我們來(lái)介紹一下。首先需要安裝一個(gè)vscode插件,點(diǎn)擊左側(cè)最下面的圖標(biāo)或者“在查看菜單中選擇命令面板,輸入install,選擇擴(kuò)展:安裝擴(kuò)展”,然后輸入“debugger for chrome”回車,點(diǎn)擊安裝即可。

然后點(diǎn)擊最左邊的倒數(shù)第二個(gè)按鈕

如果是第一次使用的話,齒輪圖標(biāo)上會(huì)有個(gè)紅點(diǎn),點(diǎn)擊選擇debugger for chrome,vscode會(huì)幫你創(chuàng)建一個(gè)配置文件,這個(gè)文件位于.vscodelaunch.json是debugger的配置文件,請(qǐng)改寫成下面的樣子。注意如果是MacOSX或者Linux,請(qǐng)把userDataDir替換成對(duì)應(yīng)的臨時(shí)目錄,另外把"webpack:///C:*":"C:/*"替換成"webpack:///*": "/*",這句是因?yàn)閍ngular-cli是采用webpack打包的,如果沒有使用angular-cli不需要添加這句。

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch Chrome against localhost, with sourcemaps",
            "type": "chrome",
            "request": "launch",
            "url": "http://localhost:4200",
            "sourceMaps": true,
            "runtimeArgs": [
                "--disable-session-crashed-bubble",
                "--disable-infobars"
            ],
            "diagnosticLogging": true,
            "webRoot": "${workspaceRoot}/src",
            //windows setup
            "userDataDir": "C:	empchromeDummyDir",
            "sourceMapPathOverrides": {
                "webpack:///C:*":"C:/*"
                //use "webpack:///*": "/*" on Linux/OSX
            }
        },
        {
            "name": "Attach to Chrome, with sourcemaps",
            "type": "chrome",
            "request": "attach",
            "port": 9222,
            "sourceMaps": true,
            "diagnosticLogging": true,
            "webRoot": "${workspaceRoot}/src",
            "sourceMapPathOverrides": {
                "webpack:///C:*":"C:/*"
            }
        }
    ]
}

現(xiàn)在你可以試著在源碼中設(shè)置一個(gè)斷點(diǎn),點(diǎn)擊debug視圖中的debug按鈕,可以嘗試右鍵點(diǎn)擊變量把它放到監(jiān)視中看看變量值或者逐步調(diào)試應(yīng)用。

本章完整代碼見: https://github.com/wpcfan/awe...

第一節(jié):Angular 2.0 從0到1 (一)
第二節(jié):Angular 2.0 從0到1 (二)
第三節(jié):Angular 2.0 從0到1 (三)
第四節(jié):Angular 2.0 從0到1 (四)
第五節(jié):Angular 2.0 從0到1 (五)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/86823.html

相關(guān)文章

  • Angular 2.x 01 (一)上最簡(jiǎn)單Angular2教程

    摘要:官方支持微軟出品,是的超集,是的強(qiáng)類型版本作為首選編程語(yǔ)言,使得開發(fā)腳本語(yǔ)言的一些問(wèn)題可以更早更方便的找到。第一個(gè)組件那么我們來(lái)為我們的增加一個(gè)吧,在命令行窗口輸入。引導(dǎo)過(guò)程通過(guò)在中引導(dǎo)來(lái)啟動(dòng)應(yīng)用。它們的核心就是。 第一節(jié):Angular 2.0 從0到1 (一)第二節(jié):Angular 2.0 從0到1 (二)第三節(jié):Angular 2.0 從0到1 (三) 第一章:認(rèn)識(shí)Angular...

    tuniutech 評(píng)論0 收藏0
  • Angular 2.x 0 1 (二)上最簡(jiǎn)單 Angular2 教程

    摘要:下面我們看看如果使用是什么樣子的,首先我們需要在組件的修飾器中配置,然后在組件的構(gòu)造函數(shù)中使用參數(shù)進(jìn)行依賴注入。 第一節(jié):Angular 2.0 從0到1 (一)第二節(jié):Angular 2.0 從0到1 (二)第三節(jié):Angular 2.0 從0到1 (三) 第二節(jié):用Form表單做一個(gè)登錄控件 對(duì)于login組件的小改造 在 hello-angularsrcapploginlogin...

    warkiz 評(píng)論0 收藏0
  • angular - 收藏集 - 掘金

    摘要:如何在中使用動(dòng)畫前端掘金本文講一下中動(dòng)畫應(yīng)用的部分。與的快速入門指南推薦前端掘金是非常棒的框架,能夠創(chuàng)建功能強(qiáng)大,動(dòng)態(tài)功能的。自發(fā)布以來(lái),已經(jīng)廣泛應(yīng)用于開發(fā)中。 如何在 Angular 中使用動(dòng)畫 - 前端 - 掘金本文講一下Angular中動(dòng)畫應(yīng)用的部分。 首先,Angular本生不提供動(dòng)畫機(jī)制,需要在項(xiàng)目中加入Angular插件模塊ngAnimate才能完成Angular的動(dòng)畫機(jī)制...

    AlexTuan 評(píng)論0 收藏0
  • Angular 2.x 01 (四)上最簡(jiǎn)單Angular2教程

    摘要:而且此時(shí)我們注意到其實(shí)沒有任何一個(gè)地方目前還需引用了,這就是說(shuō)我們可以安全地把從組件中的修飾符中刪除了。 第一節(jié):Angular 2.0 從0到1 (一)第二節(jié):Angular 2.0 從0到1 (二)第三節(jié):Angular 2.0 從0到1 (三) 作者:王芃 wpcfan@gmail.com 第四節(jié):進(jìn)化!模塊化你的應(yīng)用 一個(gè)復(fù)雜組件的分拆 上一節(jié)的末尾我偷懶的甩出了大量代碼,可能...

    sanyang 評(píng)論0 收藏0
  • 架構(gòu)~微服務(wù)

    摘要:接下來(lái)繼續(xù)介紹三種架構(gòu)模式,分別是查詢分離模式微服務(wù)模式多級(jí)緩存模式。分布式應(yīng)用程序可以基于實(shí)現(xiàn)諸如數(shù)據(jù)發(fā)布訂閱負(fù)載均衡命名服務(wù)分布式協(xié)調(diào)通知集群管理選舉分布式鎖和分布式隊(duì)列等功能。 SpringCloud 分布式配置 SpringCloud 分布式配置 史上最簡(jiǎn)單的 SpringCloud 教程 | 第九篇: 服務(wù)鏈路追蹤 (Spring Cloud Sleuth) 史上最簡(jiǎn)單的 S...

    xinhaip 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<