本項目源碼放在githubhtml
接下來開始編寫頁面組件,這裏咱們挑重點來寫,一些佈局的樣式,後面能夠看源碼。前端
咱們首先寫一個書本信息的組件,代碼以下:vue
<!-- index.component.html -->
<div class="content">
<div class="books_box">
<!-- 單個課本 -->
<div class="books_item" *ngFor="let item of [1,2,3,4,5,6,7,8,9,10]">
<img class="cover" src="https://img3.doubanio.com/view/subject/m/public/s29988481.jpg">
<div class="title"><a>像火焰像灰燼</a></div>
<div class="author">程姬</div>
</div>
</div>
</div>
複製代碼
知識點:
*ngFor
是一個 Angular 的複寫器(repeater)指令,就像angular1中的ng-for
和vuejs中的v-for
。 它會爲列表中的每項數據複寫它的宿主元素。
這時候能夠看到頁面變成下面這個樣子:
git
接下來咱們要把寫死在HTML上面的數據,抽到JS中:github
如今先新建一個books.ts
文件來定義一個Book
類,並添加id
,url
,title
和author
四個屬性:bash
// src/app/books.ts
export class Book {
id: number;
url: string;
title: string;
author: string;
}
複製代碼
而後回到index.component.ts
文件去引入它,並定義一個books
屬性,使用導入進來的Book
類做爲類型:服務器
// index.component.ts
import { Book } from '../books';
export class IndexComponent implements OnInit {
books: Book = {
id: 1,
url: 'https://img3.doubanio.com/view/subject/m/public/s29988481.jpg',
title: '像火焰像灰燼',
author: '程姬',
}
}
複製代碼
而後再改造前面的組件文件index.component.html
:微信
<!-- index.component.html -->
<div class="books_item" *ngFor="let item of [1,2,3,4,5,6,7,8,9,10]">
<img class="cover" src="{{books.url}}" alt="{{books.id}}">
<div class="title">
<a>{{books.title}}</a>
</div>
<div class="author">{{books.author}}</div>
</div>
複製代碼
接着,咱們再爲每一個課本添加一個點擊事件,來實現點擊封面圖能查看大圖的效果,如今index.component.ts
中定義一個getDetailImage
方法,並在index.component.html
中綁定該方法:app
// index.component.ts
export class IndexComponent implements OnInit {
getDetailImage(books){
alert(`正在查看id爲${books.id}的大圖!`);
}
}
複製代碼
這邊方法的具體實現,不寫,不是本文重點。下面是增長點擊事件的綁定:ide
<!-- index.component.html -->
<img class="cover" src="{{books.url}}" alt="{{books.id}}" (click)="getDetailImage(books)">
複製代碼
知識點:
(click)
是Angular用來綁定事件,它會讓 Angular 監聽這個<img>
元素的 click
事件。 當用戶點擊 <img>
時,Angular 就會執行表達式 getDetailImage(books)
。
再來,咱們引入前面學到的路由連接指令來改造HTML:
<!-- index.component.html -->
<a routerLink="/detail/{{books.id}}">{{books.title}}</a>
複製代碼
這時候,咱們在點擊書本的標題,發現頁面跳轉到URL地址爲http://localhost:4200/detail/1
的頁面,這就說明,咱們頁面的路由跳轉也成功了~
改造完成後,能夠看到,頁面顯示的仍是同樣,接下來咱們先這樣放着,由於咱們後面會進行數據模擬,和模擬服務器請求。
咱們就這樣寫好第一個單一組件,而且數據是從JS中讀取的。
這時候爲了方便後面數據渲染,咱們這裏須要模擬一些本地數據,咱們建立一個本地mock-books.ts
文件來存放模擬的數據:
// app/mock-books.ts
import { Books } from './books';
export const BookList: Books[] = [
{
id: 1,
url: 'https://img3.doubanio.com/view/subject/m/public/s29988481.jpg',
title: '像火焰像灰燼',
author: '程姬',
},
// 省略其餘9條
]
複製代碼
而後在index.component.ts
中導入模擬的數據,並將原有的books
值修改爲導入的模擬數據BookList
:
// index.component.ts
import { BookList } from '../mock-books';
books = BookList;
複製代碼
並將本來的*ngFor
中修改爲這樣,綁定真正的數據:
<!-- index.component.html -->
<div class="books_item" *ngFor="let item of books">
<img class="cover" src="{{item.url}}" alt="{{item.id}}">
<div class="title">
<a>{{item.title}}</a>
</div>
<div class="author">{{item.author}}</div>
</div>
複製代碼
當咱們寫完一個單一組件後,咱們會發現,若是咱們把每一個組件都寫到同一個HTML文件中,這是很糟糕的事情,這樣作有缺點:
爲了解決這個問題,咱們這裏就要開始使用真正的組件化思惟,將通用經常使用組件抽離出來,經過參數傳遞來控制組件的不一樣業務形態。
這即是咱們接下來要寫的主從組件。
思考一下,咱們這裏如今能抽成組件做爲公共代碼的,就是這個單個書本的內容,由於每一個書本的內容都一致,只是裏面數據的差別,因而咱們再新建一個組件:
ng g component books
複製代碼
並將前面index.component.html
中關於課本的代碼剪切到books.component.html
中來,而後刪除掉*ngFor
的內容,並將本來本地的變量books
替換成list
,這個變量咱們等會會取到:
<!-- books.component.html -->
<div class="books_item">
<img class="cover" src="{{list.url}}" alt="{{list.id}}" (click)="getDetailImage(list)">
<div class="title">
<a routerLink="/detail/{{list.id}}">{{list.title}}</a>
</div>
<div class="author">{{list.author}}</div>
</div>
複製代碼
再將這個組件,引用到它的父組件中,這裏是要引用到index.component.html
的組件中,並將前面的*ngFor
再次傳入<app-books>
:
<div class="content">
<div class="books_box">
<app-books *ngFor="let item of books"></app-books>
</div>
</div>
複製代碼
接下來要作的就是獲取到list
變量的值,顯然這個值是要從外面組件傳進來的,咱們須要在books.component.ts
引入前面定義的 Books
類 和 @Input() 裝飾器
,還要添加一個帶有 @Input() 裝飾器
的 list
屬性,另外還要記得將getDetailImage
方法也剪切過來:
// books.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { Books } from '../books';
export class BooksComponent implements OnInit {
@Input() list: Books;
constructor() { }
ngOnInit() {}
getDetailImage(books){
alert(`正在查看id爲${books.id}的大圖!`);
}
}
複製代碼
@Input() 裝飾器
介紹具體能夠查看 手冊
咱們要獲取的 list
屬性必須是一個帶有@Input()
裝飾器的輸入屬性,由於外部的 IndexComponent
組件將會綁定到它。就像這樣:
<app-books *ngFor="let list of books" [list]="item"></app-books>
複製代碼
知識點:
[list]="item"
是 Angular
的屬性綁定語法。這是一種單向數據綁定。從 IndexComponent
的 item
屬性綁定到目標元素的 list
屬性,並映射到了 BooksComponent
的 list
屬性。
作到這裏,咱們已經將BooksComponent
做爲IndexComponent
的子組件來引用了,在實際開發過程當中,這樣的父子組件關係,會用的很是多。
寫到這裏,看看咱們項目,仍是同樣正常在運行,只是如今項目中組件分工更加明確了。
如今的效果圖:
本部份內容到這結束
Author | 王平安 |
---|---|
pingan8787@qq.com | |
博 客 | www.pingan8787.com |
微 信 | pingan8787 |
每日文章推薦 | https://github.com/pingan8787/Leo_Reading/issues |
JS小冊 | js.pingan8787.com |
微信公衆號 | 前端自習課 |