Tour of Heroes應用程序有新的要求:javascript
完成後,用戶將能夠像這樣瀏覽應用程序:css
爲了知足這些要求,您將添加Angular路由器到應用程序。html
有關路由器的更多信息,請閱讀路由和導航頁面。java
當你完成這個頁面,應用程序應該看起來像這個實例(查看源代碼)。git
在繼續英雄之旅以前,請確認您具備如下結構。github
若是該應用程序還沒有運行,請啓動該應用程序。 在進行更改時,請經過從新加載瀏覽器窗口來保持運行。web
計劃以下:json
路由是導航的另外一個名稱。 路由是導航從視圖到視圖的機制。bootstrap
當前的應用程序加載AppComponent並當即顯示英雄列表。 修改後的應用程序應該提供一個可選的視圖(Dashboard和Heroes),而後默認爲其中的一個。api
AppComponent只應該處理導航,因此你能夠將Heroes的顯示從AppComponent移出並放到它本身的HeroesComponent中。
AppComponent已經專一於英雄。 將代碼移出AppComponent,將其重命名爲HeroesComponent,並建立一個單獨的AppComponent外殼。
請執行下列操做:
lib/src/heroes_component.dart (showing renamings only)
@Component( selector: 'my-heroes', templateUrl: 'heroes_component.html', styleUrls: const ['heroes_component.css'], ) class HeroesComponent implements OnInit { HeroesComponent( this._heroService, ); }
新的AppComponent是應用程序外殼。 它將在頂部有一些導航連接,下面有一個顯示區域。
執行這些步驟:
第一稿看起來是這樣的:lib/app_component.dart
import 'package:angular/angular.dart'; import 'src/hero_service.dart'; import 'src/heroes_component.dart'; @Component( selector: 'my-app', template: ''' <h1>{{title}}</h1> <my-heroes></my-heroes> ''', directives: const [HeroesComponent], providers: const [HeroService], ) class AppComponent { final title = 'Tour of Heroes'; }
刷新瀏覽器。 該應用程序仍然運行並顯示英雄。
應該在用戶點擊按鈕後顯示英雄而不是自動顯示。 換句話說,用戶應該可以導航到英雄列表。
使用Angular路由(angular_router)啓用導航。 因爲路由器在本身的包中,首先將該包添加到應用的pubspec:
並不是全部的應用程序都須要路由,這就是爲何Angular路由器處於獨立的可選軟件包中的緣由。
Angular路由器是多個服務(ROUTER_PROVIDERS)、指令(ROUTER_DIRECTIVES)和配置類的組合。 你能夠經過導入路由庫來獲得它們:lib/app_component.dart (router import)
import 'package:angular_router/angular_router.dart';
要告訴Angular您的應用使用路由,請在應用的引導程序功能中指定ROUTER_PROVIDERS:web/main.dart
import 'package:angular/angular.dart'; import 'package:angular_router/angular_router.dart'; import 'package:angular_tour_of_heroes/app_component.dart'; void main() { bootstrap(AppComponent, [ ROUTER_PROVIDERS, // Remove next line in production provide(LocationStrategy, useClass: HashLocationStrategy), ]); }
使用哪一個位置策略
默認的LocationStrategy是PathLocationStrategy,因此在生產中,可使用ROUTER_PROVIDERS,而沒必要使用LocationStrategy提供程序。 在開發過程當中,使用HashLocationStrategy更方便,由於pub serve不支持deep linking。 有關詳細信息,請參閱位置策略的LocationStrategy and browser URL styles。
接下來,將ROUTER_DIRECTIVES添加到@Component註解中,並刪除HeroesComponent:
lib/app_component.dart (directives)
directives: const [ROUTER_DIRECTIVES],
您能夠從指令列表中移除HeroesComponent,由於AppComponent不會直接顯示英雄; 這是路由器的工做。 很快你會從模板中刪除<my-heroes>。
<base href>
打開index.html並確保在<head>部分的頂部有一個<base href =「...」>元素(或者一個動態設置這個元素的腳本)。
正如在「Routing and Navigation」頁面的「 Set the base href」部分所述,示例應用程序使用如下腳本:
web/index.html (base-href)
<head> <script> // WARNING: DO NOT set the <base href> like this in production! // Details: https://webdev.dartlang.org/angular/guide/router (function () { var m = document.location.pathname.match(/^(\/[-\w]+)+\/web($|\/)/); document.write('<base href="' + (m ? m[0] : '/') + '" />'); }()); </script>
Routes 告訴路由當用戶點擊一個連接或者將一個URL粘貼到瀏覽器地址欄中時顯示哪些視圖。
建立一個路由配置(RouteConfig)來保存應用程序路由定義的列表。 定義第一個路由做爲到英雄組件的路由。lib/app_component.dart (Heroes route)
@RouteConfig(const [ const Route(path: '/heroes', name: 'Heroes', component: HeroesComponent) ])
路由定義是一個具備如下命名參數的Route對象:
在路由和導航頁面閱讀更多關於定義路由的信息。
若是您訪問localhost:8080/#/heroes,路由器應該匹配英雄路線的URL並顯示一個HeroesComponent。 可是,您必須告訴路由器在哪裏顯示組件。
爲此,在模板的末尾添加一個<router-outlet>元素。 RouterOutlet是ROUTER_DIRECTIVES之一。 當用戶經過應用程序導航時,路由器會在<router-outlet>正下方顯示每一個組件。
刷新瀏覽器,而後訪問localhost:8080 /#/ heroes。 你應該看到英雄列表。
用戶沒必要粘貼路由路徑到地址欄。 相反,向模板添加一個錨點,點擊後會觸發到HeroesComponent的導航。
修改後的模板以下所示:lib/app_component.dart (template)
template: ''' <h1>{{title}}</h1> <a [routerLink]="['Heroes']">Heroes</a> <router-outlet></router-outlet> ''',
請注意錨標記中的[routerLink]綁定。 RouterLink指令告訴路由在用戶點擊連接時的位置。
您使用連接參數列表定義了一個路由指令, 這個列表在咱們的小樣本中只有一個元素,引用的路由名稱。 回頭看看路由配置,肯定「Heroes」是到HeroesComponent的路由的名字。
瞭解路由章節中的連接參數列表。
刷新瀏覽器,瀏覽器顯示應用標題和英雄連接,但不是英雄列表。點擊英雄導航連接。地址欄更新爲 /#/heroes(或同等/#heroes),英雄列表顯示。
AppComponent如今看起來像這樣:lib/app_component.dart
import 'package:angular/angular.dart'; import 'package:angular_router/angular_router.dart'; import 'src/hero_service.dart'; import 'src/heroes_component.dart'; @Component( selector: 'my-app', template: ''' <h1>{{title}}</h1> <a [routerLink]="['Heroes']">Heroes</a> <router-outlet></router-outlet> ''', directives: const [ROUTER_DIRECTIVES], providers: const [HeroService], ) @RouteConfig(const [ const Route(path: '/heroes', name: 'Heroes', component: HeroesComponent) ]) class AppComponent { final title = 'Tour of Heroes'; }
AppComponent有一個路由,並顯示路由視圖。 爲此,爲了區別於其餘類型的組件,這種組件類型稱爲路由組件。
只有當多個視圖存在時,路由纔有意義。 要添加另外一個視圖,請建立一個佔位DashboardComponent。
lib/src/dashboard_component.dart (v1)
import 'package:angular/angular.dart'; @Component( selector: 'my-dashboard', template: '<h3>My Dashboard</h3>', ) class DashboardComponent {}
稍後您將使這個組件更加有用。
添加一個相似Heroes路由的dashboard 路由:lib/app_component.dart (Dashboard route)
const Route( path: '/dashboard', name: 'Dashboard', component: DashboardComponent, ),
目前,瀏覽器在/在地址欄中啓動。 當應用程序啓動時,它應該顯示儀表板,並在地址欄中顯示路徑 /#/dashboard 。
要作到這一點,請添加劇定向路由:lib/app_component.dart (Redirect route)
const Redirect(path: '/', redirectTo: const ['Dashboard']),
或者,您能夠將dashboard 定義爲默認路由。 在路由和導航頁面閱讀有關默認路由和重定向的更多信息。
在模板上添加dashboard 導航連接,在heroes連接上方。lib/app_component.dart (template)
template: ''' <h1>{{title}}</h1> <nav> <a [routerLink]="['Dashboard']">Dashboard</a> <a [routerLink]="['Heroes']">Heroes</a> </nav> <router-outlet></router-outlet> ''',
<nav>標籤目前尚未作任何事情,可是當您格式化連接時,它們會頗有用。
在瀏覽器中,轉至應用程序根目錄(/)並從新加載。 該應用程序顯示dashboard ,您能夠在dashboard 和heroes之間導航。
爲了讓dashboard 更有趣,您一眼就能夠看到前四名的英雄。
將template元數據替換爲指向新模板文件的templateUrl屬性,並添加以下所示的指令(還要添加必要的導入):lib/src/dashboard_component.dart (metadata)
@Component( selector: 'my-dashboard', templateUrl: 'dashboard_component.html', directives: const [CORE_DIRECTIVES, ROUTER_DIRECTIVES], )
templateUrl的值能夠是這個包或其餘包中的asset。 要在另外一個包中使用資源,請使用完整的包引用,如「package:some_other_package / dashboard_component.html」。
使用如下內容建立模板文件:lib/src/dashboard_component.html
<h3>Top Heroes</h3> <div class="grid grid-pad"> <div *ngFor="let hero of heroes"> <div class="module hero"> <h4>{{hero.name}}</h4> </div> </div> </div>
* ngFor再次用於遍歷英雄列表並顯示他們的名字。 額外的<div>元素將有助於之後的格式化樣式。
要填充組件的英雄列表,您能夠從新使用HeroService。
以前,您從HeroesComponent的提供程序列表中刪除了HeroService,並將其添加到AppComponent的提供程序列表中。 這個舉動建立了一個單例HeroService實例,可用於應用程序的全部組件。 Angular注入HeroService,您能夠在DashboardComponent中使用它。
在dashboard_component.dart中,添加如下導入語句。lib/src/dashboard_component.dart (imports)
import 'dart:async'; import 'package:angular/angular.dart'; import 'package:angular_router/angular_router.dart'; import 'hero.dart'; import 'hero_service.dart';
如今建立DashboardComponent類,以下所示:lib/src/dashboard_component.dart (class)
class DashboardComponent implements OnInit { List<Hero> heroes; final HeroService _heroService; DashboardComponent(this._heroService); Future<Null> ngOnInit() async { heroes = (await _heroService.getHeroes()).skip(1).take(4).toList(); } }
HeroesComponent也使用這種邏輯:
在這個儀表板中你指定了四個英雄(第二,第三,第四和第五)。
刷新瀏覽器以查看新儀表板中的四個英雄名稱。
雖然所選英雄的詳細信息顯示在HeroesComponent的底部,但用戶應該可以經過如下其餘方式導航到HeroDetailComponent:
您能夠在AppComponent中添加到HeroDetailComponent的路由,其中定義了其餘路由。
新的路由是不尋常的,你必須告訴HeroDetailComponent顯示哪一個英雄。 您沒必要告訴HeroesComponent或DashboardComponent任何東西。
目前,父HeroesComponent使用以下綁定將組件的hero屬性設置爲hero對象:
<hero-detail [hero]="selectedHero"></hero-detail>
可是這種綁定在任何路由腳本中都不起做用。
您能夠將英雄的id添加到路由路徑。 當路由到英雄的id爲11,你能夠指望看到這樣的路徑:
/detail/11
/ detail /部分是不變的。 尾隨的數字id在英雄與英雄間變換。 您須要使用表明英雄id的參數來表示路由的可變部分。
首先,導入英雄細節組件:
import 'src/hero_detail_component.dart';
接下來,添加如下路由:lib / app_component.dart(HeroDetail route)
const Route( path: '/detail/:id', name: 'HeroDetail', component: HeroDetailComponent, ),
路徑中的冒號(:)表示:id在導航到HeroDetailComponent時是特定英雄id的佔位符。
你已經完成了應用程序的路由。
您沒有向模板添加英雄詳情連接,由於用戶單擊導航連接不是爲了查看特定的英雄; 而是點擊一個英雄的名字,無論名字是顯示在儀表板仍是英雄列表中。 可是,直到HeroDetailComponent被修改並準備好導航到這個時候,它纔會起做用。
如下是HeroDetailComponent如今的樣子:lib/src/hero_detail_component.dart (current)
import 'package:angular/angular.dart'; import 'package:angular_forms/angular_forms.dart'; import 'hero.dart'; @Component( selector: 'hero-detail', template: ''' <div *ngIf="hero != null"> <h2>{{hero.name}} details!</h2> <div><label>id: </label>{{hero.id}}</div> <div> <label>name: </label> <input [(ngModel)]="hero.name" placeholder="name"/> </div> </div> ''', directives: const [CORE_DIRECTIVES, formDirectives], ) class HeroDetailComponent { @Input() Hero hero; }
該模板不會改變。 英雄的名字將顯示相同的方式。 主要的變化是如何獲得英雄的名字。
您將再也不接收父組件屬性綁定中的英雄,所以您能夠從hero字段中刪除@Input()註解:lib/src/hero_detail_component.dart (hero with @Input removed)
class HeroDetailComponent implements OnInit { Hero hero; }
新的HeroDetailComponent將從路由器的RouteParams服務中獲取id參數,並使用HeroService來獲取具備該id的英雄。
添加如下導入:lib/src/hero_detail_component.dart (added-imports)
import 'dart:async'; import 'package:angular_router/angular_router.dart'; import 'hero_service.dart';
將RouteParams,HeroService和Location服務注入到構造函數中,並將其值保存在私有字段中:lib/src/hero_detail_component.dart (constructor)
final HeroService _heroService; final RouteParams _routeParams; final Location _location; HeroDetailComponent(this._heroService, this._routeParams, this._location);
告訴類實現OnInit接口。
class HeroDetailComponent implements OnInit {
在ngOnInit()生命週期的鉤子中,從RouteParams服務中提取id參數值,並使用HeroService來獲取具備該id的英雄。lib/src/hero_detail_component.dart (ngOnInit)
Future<Null> ngOnInit() async { var _id = _routeParams.get('id'); var id = int.parse(_id ?? '', onError: (_) => null); if (id != null) hero = await (_heroService.getHero(id)); }
注意如何經過調用RouteParams.get()方法來提取id。
英雄id是一個數字。 路由參數始終是字符串。 因此路由參數值被轉換成一個數字。
在ngOnInit()中,你使用了HeroService尚未的getHero()方法。 要解決這個問題,打開HeroService,並添加一個getHero()方法,經過id從getHeroes()過濾英雄列表。lib/src/hero_service.dart (getHero)
Future<Hero> getHero(int id) async => (await getHeroes()).firstWhere((hero) => hero.id == id);
用戶有幾種方式導航到HeroDetailComponent。
要在其餘地方導航,用戶能夠單擊AppComponent中的兩個連接之一,或單擊瀏覽器的後退按鈕。 如今添加第三個選項,一個goBack()方法,使用您以前注入的Location服務在瀏覽器的歷史堆棧中向後導航一步。
lib/src/hero_detail_component.dart (goBack)
void goBack() => _location.back();
回頭太遠可能會把用戶帶出應用程序。 在一個真正的應用程序中,您可使用routerCanDeactivate()掛鉤來防止此問題。 在CanDeactivate頁面上閱讀更多信息。
您將使用綁定到後退按鈕的事件鏈接此方法,您將添加到組件模板。
<button (click)="goBack()">Back</button>
將模板遷移到名爲hero_detail_component.html的文件:lib/src/hero_detail_component.html
<div *ngIf="hero != null"> <h2>{{hero.name}} details!</h2> <div> <label>id: </label>{{hero.id}}</div> <div> <label>name: </label> <input [(ngModel)]="hero.name" placeholder="name" /> </div> <button (click)="goBack()">Back</button> </div>
更新組件templateUrl元數據指向您剛剛建立的模板文件。lib/src/hero_detail_component.dart (metadata)
@Component( selector: 'hero-detail', templateUrl: 'hero_detail_component.html', directives: const [CORE_DIRECTIVES, formDirectives], )
刷新瀏覽器並訪問localhost:8080/#details/11. 應該顯示英雄11的詳細信息。 在儀表板或英雄列表中選擇英雄不起做用。 你會接下來的處理。
當用戶選擇儀表板中的英雄時,應用程序應該導航到HeroDetailComponent以容許用戶查看和編輯選擇的英雄。
儀表板英雄的行爲應該像錨標籤:當懸停在英雄的名字,目標網址應該顯示在瀏覽器的狀態欄,用戶應該可以複製連接或在新標籤打開英雄詳細信息視圖。
爲了達到這個效果,打開dashboard_component.html並用一個錨點替換<div * ngFor ...>元素(子元素保持不變):lib/src/dashboard_component.html (repeated <a> tag)
<a *ngFor="let hero of heroes" [routerLink]="['HeroDetail', {id: hero.id.toString()}]" class="col-1-4"> <div class="module hero"> <h4>{{hero.name}}</h4> </div> </a>
注意[routerLink]綁定。 如本頁「路由連接」部分所述,AppComponent模板中的頂級導航將路由器連接設置爲目標路由,/dashboard 和/ heroes的固定名稱。
此次,您綁定到包含連接參數列表的表達式。 該列表包含兩個元素:目標路由的名稱和設置爲當前英雄id值的路由參數。
這兩個列表項與您以前添加的參數化英雄細節路由定義中的名稱和:id相對應:lib/app_component.dart (HeroDetail route)
const Route( path: '/detail/:id', name: 'HeroDetail', component: HeroDetailComponent, ),
刷新瀏覽器並從儀表板中選擇一個英雄; 該應用程序導航到該英雄的細節。
在HeroesComponent中,當前的模板展現了一個「主/細節」風格,頂部是英雄列表,下方是選定的英雄的詳細信息。lib/src/heroes_component.html
<h2>My Heroes</h2> <ul class="heroes"> <li *ngFor="let hero of heroes" [class.selected]="hero === selectedHero" (click)="onSelect(hero)"> <span class="badge">{{hero.id}}</span> {{hero.name}} </li> </ul> <hero-detail [hero]="selectedHero"></hero-detail>
你不會再在這裏顯示完整的HeroDetailComponent。 相反,您將在本身的頁面上顯示英雄細節,並按照您在儀表板中所作的方式路由到它。 進行這些更改:
當用戶從列表中選擇一個英雄時,他們不會進入詳細頁面。 相反,他們會在此頁面上看到一個迷你細節,而且必須單擊一個按鈕才能導航到完整的詳細信息頁面。
在模板底部添加如下HTML片斷,在<hero-detail>以前的地方:lib/src/heroes_component.html (mini detail)
<div *ngIf="selectedHero != null"> <h2> {{selectedHero.name | uppercase}} is my hero </h2> <button (click)="gotoDetail()">View Details</button> </div>
點擊一個英雄(但不要如今嘗試,由於它不會工做),用戶應該在英雄列表下面看到這樣的東西:
因爲管道運算符(|)以後的插值綁定中包含的uppercase管道,英雄的名稱將以大寫字母顯示。
{{selectedHero.name | uppercase}} is my hero
管道是格式化字符串,貨幣金額,日期和其餘顯示數據的好方法。 有幾個管道是已提供的,你能夠寫你本身的。
警告在模板中使用Angular管道以前,須要將其列在組件的@Component註解的pipes參數中。 您能夠單獨添加管道,或者爲了方便起見,可使用COMMON_PIPES組。lib/src/heroes_component.dart (pipes)
@Component( selector: 'my-heroes', pipes: const [COMMON_PIPES], )
在「Pipes」頁面上閱讀有關管道的更多信息。
刷新瀏覽器。 從英雄列表中選擇英雄將激活迷你細節視圖。 查看詳細信息按鈕不起做用。
響應按鈕單擊,HeroesComponent導航到HeroesDetailComponent。 按鈕的點擊事件綁定到一個gotoDetail()方法,該方法應該經過告訴路由器去哪裏命令性地導航。
這種方法須要對組件類進行如下更改:
這裏是修改後的HeroesComponent類:lib/src/heroes_component.dart (class)
class HeroesComponent implements OnInit { final HeroService _heroService; final Router _router; List<Hero> heroes; Hero selectedHero; HeroesComponent( this._heroService, this._router ); Future<Null> getHeroes() async { heroes = await _heroService.getHeroes(); } void ngOnInit() => getHeroes(); void onSelect(Hero hero) => selectedHero = hero; Future<Null> gotoDetail() => _router.navigate([ 'HeroDetail', {'id': selectedHero.id.toString()} ]); }
在gotoDetail()中,你正在向路由器的navigate()方法傳遞一個兩元素連接參數列表(一個名字和路由參數),就像你在DashboardComponent中的[routerLink]綁定中同樣。
刷新瀏覽器並開始點擊。 用戶能夠在應用程序周圍進行導航,從儀表板到英雄詳細信息,而後返回,從英雄列表到英雄詳細信息,再次回到英雄。
你已經達到推進這個頁面的全部導航要求。
該應用程序是功能,但它須要樣式。 儀表板英雄應顯示在一排矩形。 爲此目的,您已經收到了大約60行CSS,包括一些簡單的媒體查詢響應式設計。
正如您如今所知,將CSS添加到組件樣式元數據將會隱藏組件邏輯。 相反,您將添加CSS來分隔.css文件。
在lib / src文件夾中建立一個dashboard_component.css文件,並在組件元數據的styleUrls列表屬性中引用該文件,以下所示:
lib / src/dashboard_component.dart(styleUrls)
@Component( selector: 'my-dashboard', templateUrl: 'dashboard_component.html', styleUrls: const ['dashboard_component.css'], directives: const [CORE_DIRECTIVES, ROUTER_DIRECTIVES], )
lib / src/dashboard_component.css
[class*='col-'] { float: left; text-decoration: none; padding-right: 20px; padding-bottom: 20px; } [class*='col-']:last-of-type { padding-right: 0; } *, *:after, *:before { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } h3 { text-align: center; margin-bottom: 0; } h4 { position: relative; } .grid { margin: 0; } .col-1-4 { width: 25%; } .module { padding: 20px; text-align: center; color: #eee; max-height: 120px; min-width: 120px; background-color: #607D8B; border-radius: 2px; } .module:hover { background-color: #EEE; cursor: pointer; color: #607d8b; } .grid-pad { padding: 10px 0; } .grid-pad > [class*='col-']:last-of-type { padding-right: 20px; } @media (max-width: 600px) { .module { font-size: 10px; max-height: 75px; } } @media (max-width: 1024px) { .grid { margin: 0; } .module { min-width: 60px; } }
在lib / src文件夾中建立一個hero_detail_component.css文件,並在組件元數據的styleUrls列表中引用該文件:
lib / src/hero_detail_component.dart(styleUrls)
@Component( selector: 'hero-detail', templateUrl: 'hero_detail_component.html', styleUrls: const ['hero_detail_component.css'], directives: const [CORE_DIRECTIVES, formDirectives], )
lib / src/hero_detail_component.css
label { display: inline-block; width: 3em; margin: .5em 0; color: #607D8B; font-weight: bold; } input { height: 2em; font-size: 1em; padding-left: .4em; } button { margin-top: 20px; font-family: Arial; background-color: #eee; border: none; padding: 5px 10px; border-radius: 4px; cursor: pointer; cursor: hand; } button:hover { background-color: #cfd8dc; } button:disabled { background-color: #eee; color: #ccc; cursor: auto; }
在lib文件夾中建立一個app_component.css文件,並在組件元數據的styleUrls列表中引用該文件:
lib / app_component.dart(styleUrls)
styleUrls: const ['app_component.css'],
lib / app_component.css
h1 { font-size: 1.2em; color: #999; margin-bottom: 0; } h2 { font-size: 2em; margin-top: 0; padding-top: 0; } nav a { padding: 5px 10px; text-decoration: none; margin-top: 10px; display: inline-block; background-color: #eee; border-radius: 4px; } nav a:visited, a:link { color: #607D8B; } nav a:hover { color: #039be5; background-color: #CFD8DC; } nav a.router-link-active { color: #039be5; }
提供的CSS使AppComponent中的導航連接更像可選按鈕。 早些時候,你用<nav>元素包圍了這些連接:
router-link-active 類
Angular路由器將router-link-active類添加到其路由與活動路由相匹配的HTML導航元素。 你所要作的就是定義它的風格。
將樣式添加到組件時,能夠將組件須要的全部內容(HTML,CSS和代碼)一塊兒放在一個方便的位置。 把它打包起來很容易,在其餘地方從新使用組件。
您還能夠在任何組件以外的應用程序級別建立樣式。
設計師提供了一些基本樣式來應用於整個應用程序的元素。 這些對應於您在安裝期間先前安裝的全套主樣式。 這是一個摘錄:web/styles.css (excerpt)
@import url(https://fonts.googleapis.com/css?family=Roboto); @import url(https://fonts.googleapis.com/css?family=Material+Icons); /* Master Styles */ h1 { color: #369; font-family: Arial, Helvetica, sans-serif; font-size: 250%; } h2, h3 { color: #444; font-family: Arial, Helvetica, sans-serif; font-weight: lighter; } body { margin: 2em; } body, input[text], button { color: #888; font-family: Cambria, Georgia; } /* ··· */ /* everywhere else */ * { font-family: Arial, Helvetica, sans-serif; }
若有必要,建立文件web / styles.css。 確保文件包含此處提供的主要樣式。 另外編輯web / index.html來引用這個樣式表。
web / index.html(link ref)
<link rel="stylesheet" href="styles.css">
如今看看應用程序。 儀表板,英雄和導航連接的樣式。
查看此頁面的實例(查看源代碼)中的示例源代碼。 確認您具備如下結構:
如下是您在此頁面中所取得的成果:
前方的路
你有不少基礎,你須要創建一個應用程序。 您仍然缺乏一個關鍵部分:遠程數據訪問。
在下一頁中,您將使用http從服務器檢索到的數據替換模擬數據。