英雄指南——多組件

版本:4.0.0+2

此時(shí)AppComponent做了所有的事情慨蓝。起初,它顯示一個(gè)單一英雄的詳情竹伸。然后泥栖,它成了有一列英雄和英雄詳情的主從結(jié)構(gòu)。很快會(huì)有新的需求和功能勋篓。你不能把所有功能堆積在一個(gè)組件中吧享;那樣不利于維護(hù)。

你需要把它拆分到子組件生巡,每個(gè)組件專注于特定的任何或工作流程耙蔑。最終,AppComponent會(huì)成為一個(gè)簡(jiǎn)單的包含這些子組件的殼孤荣。

在本章,你將通過提取英雄詳情到一個(gè)獨(dú)立的须揣、可復(fù)用的組件朝那方向邁出第一步盐股。當(dāng)你做完這一切,應(yīng)用看起來應(yīng)該這樣——在線示例 (查看源碼)耻卡。

我們離開的地方

在開始本章之前疯汁,先檢查一下,是否已經(jīng)有了如下目錄結(jié)構(gòu)卵酪。如果沒有幌蚊,回到上一章谤碳。

如果應(yīng)用不運(yùn)行了,啟動(dòng)應(yīng)用溢豆。當(dāng)你做出修改時(shí)蜒简,通過刷新瀏覽器保持繼續(xù)運(yùn)行。

制作英雄詳情組件

創(chuàng)建一個(gè)名為hero_detail_component.dart的文件漩仙。這個(gè)文件有一個(gè)新的 HeroDetailComponent搓茬。

Angular 慣例

  • 組件類名應(yīng)該使用大寫駝峰命名,并且以 “Component” 結(jié)尾队他。
  • 組件文件名應(yīng)該使用蛇形——小寫加下劃線分隔符命名卷仑,并且以_component.dart結(jié)尾。HeroDetailComponent類就在hero_detail_component.dart文件中麸折。
  • 內(nèi)部實(shí)現(xiàn)文件應(yīng)該放在lib/src目錄下锡凝。請(qǐng)看 pub 包布局慣例了解詳情。

如下所示垢啼,開始編寫HeroDetailComponent

// lib/src/hero_detail_component.dart (initial version)

import 'package:angular/angular.dart';
import 'package:angular_forms/angular_forms.dart';

@Component(
  selector: 'hero-detail',
  directives: const [CORE_DIRECTIVES, formDirectives],
)
class HeroDetailComponent {
}

要定義組件私爷,總是要導(dǎo)入主要的 Angular 庫(kù)。

@Component注解為組件提供了 Angular 元數(shù)據(jù)膊夹。CSS 選擇器名hero-detail將會(huì)匹配元素標(biāo)簽衬浑,以識(shí)別在父組件模板內(nèi)的本組件。在本教程快結(jié)束的部分放刨,你將添加一個(gè)<hero-detail>元素到AppComponent模板工秩。

英雄詳情模板

要移動(dòng)英雄詳情視圖到HeroDetailComponent,從AppComponent模板的底部剪切英雄詳情內(nèi)容进统,并把它粘貼到新的@Component注解的template參數(shù)中助币。

HeroDetailComponent有一個(gè) hero,而不是 selectedHero螟碎。使用 ”hero“ 替換模板中的每一處 ”selectedHero“眉菱。當(dāng)你昨晚這一切,新的模板看起來這樣:

// lib/src/hero_detail_component.dart (template)

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>''',

添加 hero 屬性

HeroDetailComponent模板綁定到組件的hero屬性掉分。把這個(gè)屬性及其必備的導(dǎo)入一塊添加到HeroDetailComponent類俭缓。

// lib/src/hero_detail_component.dart (hero)

import 'hero.dart';

class HeroDetailComponent {
  Hero hero;
}

hero 屬性是一個(gè)輸入屬性

在本章稍后的部分,父組件AppComponent通過綁定它的selectedHero屬性到HeroDetailComponenthero屬性來會(huì)告訴子組件HeroDetailComponent顯示哪個(gè)英雄酥郭。綁定看起來是這樣的:

<hero-detail [hero]="selectedHero"></hero-detail>

放在等號(hào) (=) 左邊方括號(hào)中的hero屬性华坦,使其成為了屬性綁定表達(dá)式的目標(biāo)。你必須聲明一個(gè)目標(biāo)綁定屬性為一個(gè)輸入屬性不从。否則惜姐,Angular 拒絕綁定,并拋出一個(gè)錯(cuò)誤椿息。

通過使用@Input注解歹袁,聲明hero是一個(gè)輸入屬性:

// lib/src/hero_detail_component.dart (Input annotation)

@Input()
Hero hero;

更多關(guān)于輸入屬性的內(nèi)容坷衍,請(qǐng)看屬性指令

沒錯(cuò)条舔。hero屬性是HeroDetailComponent類中唯一的東西枫耳。它做的事情就是通過它的hero輸入屬性接收一個(gè)英雄對(duì)象,然后使用它的模板綁定到該屬性逞刷。下面是完成后的HeroDetailComponent嘉涌。

// lib/src/hero_detail_component.dart

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;
}

添加 HeroDetailComponent 到 AppComponent

AppComponent仍然是主從結(jié)構(gòu)的視圖。在你從模板中剪切出那一部分之前夸浅,它被用來在它自身上顯示英雄詳情÷刈睿現(xiàn)在,它將委托給HeroDetailComponent帆喇。

首先導(dǎo)入HeroDetailComponent以使AppComponent可以引用它警医。

import 'src/hero_detail_component.dart';

想想那個(gè)在HeroDetailComponent元數(shù)據(jù)中的 CSS 選擇器hero-detail。那就是表示HeroDetailComponent元素的標(biāo)簽名坯钦。

在靠近AppComponent模板的底部添加<hero-detail>元素预皇,那里是之前英雄詳情待的地方。

通過綁定AppComponentselectedHero屬性到HeroDetailComponenthero屬性婉刀,協(xié)調(diào)主組件AppComponentHeroDetailComponent吟温。

<hero-detail [hero]="selectedHero"></hero-detail>

現(xiàn)在每次selectedHero發(fā)生變化,HeroDetailComponent就獲取一個(gè)新的英雄來顯示突颊。

修改后的AppComponent模板看起來是這樣:

// lib/app_component.html

<h1>{{title}}</h1>
<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>

每次用戶選擇一個(gè)新英雄詳情信息應(yīng)該會(huì)更新鲁豪。然而現(xiàn)在什么事都沒發(fā)生!點(diǎn)擊一個(gè)英雄律秃。沒有詳情信息爬橡。如果你在瀏覽器開發(fā)工具的控制臺(tái)尋找錯(cuò)誤。沒有錯(cuò)誤棒动。

這好像是 Angular 忽略了新標(biāo)簽糙申。原因就是它忽略了新的標(biāo)簽。

指令列表

瀏覽器會(huì)忽視它無法識(shí)別的 HTML 標(biāo)簽和屬性(attribute)船惨,Angular同樣如此柜裸。

你已經(jīng)導(dǎo)入HeroDetailComponent,并在模板中使用了<hero-detail>掷漱,但是你并沒有告訴Angular粘室。

正如你之前為內(nèi)置 Angular 指令所做的,通過在元數(shù)據(jù)directives列表中列出英雄詳情組件來告訴 Angular卜范。你再也不需要formDirectives了,所以刪除它以及在文件頂部的angular_forms導(dǎo)入:

// lib/app_component.dart (directives)

directives: const [CORE_DIRECTIVES, HeroDetailComponent],

刷新瀏覽器鹿榜。應(yīng)用正常工作了海雪。

應(yīng)用設(shè)計(jì)變化

之前一樣锦爵,每當(dāng)用戶點(diǎn)擊了一個(gè)英雄的名字,該英雄的詳情就顯示在了英雄列表的下方奥裸。但現(xiàn)在险掀,HeroDetailComponent用來顯示那些詳情。

把原來的AppComponent重構(gòu)成兩個(gè)組件帶來如下收益湾宙,無論是現(xiàn)在還是將來:

  1. 你通過減少AppComponent的職責(zé)簡(jiǎn)化了該組件樟氢。
  2. 你可以把HeroDetailComponent改進(jìn)成一個(gè)功能豐富的英雄編輯器,而不用改動(dòng)父組件AppComponent侠鳄。
  3. 你可以改進(jìn)AppComponent埠啃,而不用改動(dòng)英雄詳情視圖。
  4. 將來你可以在其它組件的模板中重復(fù)使用HeroDetailComponent伟恶。

回顧應(yīng)用結(jié)構(gòu)

驗(yàn)證你是否有如下結(jié)構(gòu):

你已經(jīng)走過的路

在本章中你完成的內(nèi)容如下:

  • 創(chuàng)建了一個(gè)可復(fù)用的組件碴开。
  • 學(xué)會(huì)了如何讓一個(gè)組件接收輸入。
  • 學(xué)會(huì)了在directives列表中聲明應(yīng)用指令博秫。
  • 學(xué)會(huì)了把父組件綁定到子組件潦牛。

應(yīng)用看起來應(yīng)該這樣——在線示例 (查看源碼)。

下一步

服務(wù)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末挡育,一起剝皮案震驚了整個(gè)濱河市巴碗,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌即寒,老刑警劉巖橡淆,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蒿叠,居然都是意外死亡明垢,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門市咽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來痊银,“玉大人,你說我怎么就攤上這事施绎∷莞铮” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵谷醉,是天一觀的道長(zhǎng)致稀。 經(jīng)常有香客問我,道長(zhǎng)俱尼,這世上最難降的妖魔是什么抖单? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上矛绘,老公的妹妹穿的比我還像新娘耍休。我一直安慰自己,他們只是感情好货矮,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布羊精。 她就那樣靜靜地躺著,像睡著了一般囚玫。 火紅的嫁衣襯著肌膚如雪喧锦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天抓督,我揣著相機(jī)與錄音燃少,去河邊找鬼。 笑死本昏,一個(gè)胖子當(dāng)著我的面吹牛供汛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播涌穆,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼怔昨,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了宿稀?” 一聲冷哼從身側(cè)響起趁舀,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎祝沸,沒想到半個(gè)月后矮烹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡罩锐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年奉狈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涩惑。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡仁期,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出竭恬,到底是詐尸還是另有隱情跛蛋,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布痊硕,位于F島的核電站赊级,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏岔绸。R本人自食惡果不足惜理逊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一橡伞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧挡鞍,春花似錦骑歹、人聲如沸预烙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)扁掸。三九已至翘县,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谴分,已是汗流浹背锈麸。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留牺蹄,地道東北人忘伞。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像沙兰,于是被迫代替她去往敵國(guó)和親氓奈。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 版本:4.0.0+2 有一些英雄指南應(yīng)用的新需求: 添加一個(gè)儀表盤 視圖鼎天。 添加在英雄 視圖和 儀表盤 視圖之間導(dǎo)...
    soojade閱讀 1,294評(píng)論 0 0
  • 版本:4.0.0+2 隨著英雄指南應(yīng)用的進(jìn)化舀奶,你將會(huì)添加更多的需要訪問英雄數(shù)據(jù)的組件。 你將創(chuàng)建一個(gè)單獨(dú)的可復(fù)用的...
    soojade閱讀 501評(píng)論 0 1
  • 版本:v4.0.0+2 在這一章斋射,你將擴(kuò)展英雄指南應(yīng)用來顯示一列英雄育勺,并允許用戶來選擇一個(gè)英雄,同時(shí)顯示這個(gè)英雄的...
    soojade閱讀 540評(píng)論 0 1
  • 版本:Angular 5.0.0-alpha AngularDart(本文檔中我們通常簡(jiǎn)稱 Angular ) 是...
    soojade閱讀 832評(píng)論 0 4
  • 1)常見的幾種異常 空指針異常NullPointerException 類強(qiáng)制轉(zhuǎn)換異常ClassCastExcep...
    huhu502閱讀 292評(píng)論 2 1