好了,前面簡單介紹了Angular2的基本開發,並且寫了一個非常簡單的組件,這篇文章我們將要學會編寫多個組件並且有主從關系
現在,假設我們要做一個博客,博客的的文章具有主從關系,文章和文章詳情;現在,我們新建一個Article的文件夾和其組件的基本架構(順便說一下,我使用的是vs code 有個Angular2 fiels的插件,可以直接建立)
效果如下

我們需要顯示博客,那就要建立一個blogdata的數據來源,這里為了方便我們直接采用本地變量的模式來做;為了保證功能單一性原則,我們新建一個data的文件夾,在里面建立Blog類
export class Blog{
id:number;
title:string;
}
export let BLOGS:Blog[]=[
{ id:1,title:"號外號外?奧巴馬要下台啦"},
{ id:2,title:"什么?奧巴馬要下台啦?"},
{ id:3,title:"號外號外?川普要上台了"},
{ id:4,title:"啥?我大四川人也要當美國總統了?"},
{ id:5,title:"mdzz,一群麻瓜,統統查殺"},
{ id:6,title:"首推龍文,必須出具"}
]
然后在我們的Article組件中導入它
import { Component } from '@angular/core';
import {BLOGS,Blog} from '../data/blog';
@Component({
selector: 'ngarticle',
templateUrl: './article.component.html',
styleUrls:['./article.component.css']
})
export class ArticleComponent {
blogList:Blog[];
constructor()
{
this.blogList=BLOGS;
}
}
由於article是html自帶的標簽,我們使用ngarticle作為選擇器
然后,我們開始編寫我們的組件模板 article.component.html
<div class="article">
<ul class="articleList">
<li *ngFor="let blog of blogList">
<a>
{{blog.id}}:{{blog.title}}
</a>
</li>
</ul>
</div>
接下來是article.component.css
.articleList {
list-style: none;
}
.articleList li {
position: relative;
width: 100%;
font-size:16px;
border-bottom: 1px dashed #d9d9d9;
box-sizing: border-box;
border-radius:2px;
}
.articleList li > a {
position:relative;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding: 15px 25px;
display: block;
width: 100%;
color:#333;
height:100%;
}
.articleList li > span {
position:relative;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding: 15px 25px;
display: block;
color:#000;
height:100%;
background:69aa6f
}
.articleList li > a:hover {
color: #69aa6f;
transition: color 0.3s, box-shadow 0.3s;
}
.articleList li:hover {
background: #efefef;
}
完成之后,在我們的app.component.html中使用它
<ngarticle></ngarticle>
然后在命令行中進入項目根目錄,使用ng serve命令執行,然后我們就得到了一個錯誤

錯誤顯示我們的ngarticle是一個未知的組件,未知怎么辦,注冊嘛,所有的Angular組件都要注冊(聲明)之后才能使用,具體方法如下
打開我們的App.Module.ts,我們像聲明AppComponent一樣聲明我們的ArticleComponent,方法就是在declaration中添加我們的組件,這個declaration數組就是我們的組件聲明的地方,所有的組件都需要在這里聲明之后才可以使用
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 { ArticleComponent } from './article/article.component';
@NgModule({
declarations: [
AppComponent,
ArticleComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
到此,效果如下

然后我們需要一個顯示明細的東西,我們來做個顯示明細編輯吧
新建一個article-detail組件,和上邊一樣,文件夾
articledetail.component.ts
import { Component, OnInit,Input } from '@angular/core';
import {BLOGS,Blog} from '../data/blog';
@Component({
selector: 'article-detail',
templateUrl: './articledetail.component.html',
styleUrls:['./articledetail.component.css']
})
export class ArticledetailComponent implements OnInit {
@Input() blog:Blog;
ngOnInit() { }
}
這里我們注意到多了一個@Input()裝飾器,這個是用來接受組件輸入的,待會兒我們修改article.component.html的時候你就知道是干什么的了
articledetail.component.html
<div class="articledetail" *ngIf="blog">
<h2>文章明細</h2>
<div class="content">
<div class="row">
<span >ID</span>
<span>{{blog.id}}</span>
</div>
<div class="row">
<span >Title</span>
<input type="text" class="myInput" [(ngModel)]="blog.title"/>
</div>
</div>
</div>
這里用了*ngIf 值為blog,表示如果blog有值,為真,那么就顯示內容,否則不顯示
我們注意到這里又多了一個[(ngModel)],簡單就理解為input一類標簽的值綁定,雙向的哦
articledetail.component.css
.articledetail {
margin:20px;
width: 100%;
margin: 0 auto;
}
h2{
text-align: center;
}
.row{
width: 100%;
padding: 10px 20px;
}
.row>span{
margin-left: 25px;
}
.myInput{
height: 36px;
line-height: 36px;
border: 0px;
border-bottom: 2px solid #000;
padding: 6px 12px;
box-shadow: 0px 5px 10px #ccc;
width: auto;
}
因為加入了detail組件,我們先到app.module.ts中注冊(聲明)下,代碼我就不貼了,大家都會了
然后是修改剛才的article組件
article.component.ts
import { Component } from '@angular/core';
import {BLOGS,Blog} from '../data/blog';
@Component({
selector: 'ngarticle',
templateUrl: './article.component.html',
styleUrls:['./article.component.css']
})
export class ArticleComponent {
blogList:Blog[];
selectedBlog:Blog;
constructor()
{
this.blogList=BLOGS;
}
selectBlog(blog:Blog)
{
this.selectedBlog=blog;
}
}
然后是article.component.html
<div class="article">
<ul class="articleList">
<li *ngFor="let blog of blogList" (click)="selectBlog(blog)">
<a>
{{blog.id}}:{{blog.title}}
</a>
</li>
</ul>
<div>
<article-detail [blog]="selectedBlog"></article-detail>
</div>
</div>
我們看到article.component.ts中新增了一個屬性selectedBlog,多了一個事件 selectBlog;這個事件通過(click)="selectBlog(blog)"綁定到了li標簽的點擊事件上,沒錯,Angular的點擊事件就是這樣么綁定的,然后我們在下方看到了我們的article-detail 組件的標簽,里面有個 [blog]="selectedBlog",結合到剛才detail組件的@Input() blog:Blog 屬性,我們就明白了,Input故名思議就是輸入,可以接收父組件的參數;
這里簡單聊一聊[blog]類似的傳值,[X]會將值綁定到組件或者單個標簽的prototype(非attr)上,比如一個input標簽有value 的prototy,我們也可以使用這樣的綁定,你可以在article-detail組件中的input試一試,而這種綁定是單向的。由此,我們聯想到剛才的[(ngModel)],好吧,其實[()]語法相當於兩個語法,一個是[value]值綁定。一個是(input)事件的綁定;可以理解為
[ngModel]="blog.title"+(ngModelChange)="blog.title=$event";這兩個事件更原始的模樣是[value]="blog.title"+(input)="blog.title=$event.target.value",不過我們不用去關心Angular2幫我們做的這些事情,知道怎么用就行了吧
行文到此,我們該來看下效果了

結束語:到此我們可以完整得編寫組件了,也知道了一些組件間的交互模式,嗨,也不知道多說些啥,下一篇文章我們將要了解Angular的服務
更新ing。。。
項目已經放到了gitbub上,地址 https://github.com/SeeSharply/LearnAngular
本文章的提交 https://github.com/SeeSharply/LearnAngular/tree/a877676846b22b6dbe5430d02b01d25fb5463c61
