[7天學會ReactJS] Day4. 製作購物車畫面 -Reactstrap
同學們好,今天我們要來套用UI Framework。不管是自己練習或者是開發專案,使用UI Framework的話就可以省去許多刻CSS的功夫唷!
React可以使用的UI Framework有許多套,今天要介紹的是 Reactstrap ,它是將 Bootstrap 4 做成React Component的Framework,使用上來說和原本Bootstrap 4用法類似,比較容易上手,所以我們推薦新手使用Reactstrap。
和Bootstrap 4用法差異
首先呢,我們先看看Bootstrap 4和Reactstrap 套用Button時的差異吧。
// Bootstrap 4<button type="button" class="btn btn-primary">Primary</button>// Reactstrap
import { Button } from 'reactstrap';<Button color="primary">primary</Button>
看出來了嗎,Bootstrap
使用css調整DOM元件;而Reactstrap
將其做成Component,並透過props設定樣式。
本日目標
好的,那我們就開始來實作吧,今天的目標是做出下面的畫面。
[最終成果]
1. 安裝Reactstrap
npm install bootstrap@4.0.0-alpha.6 --save
npm install --save reactstrap react-addons-transition-group react-addons-css-transition-group
首先,跟著Reactstrap
官網步驟進行npm安裝。
第一行是安裝bootstrap
套件,因為Reactstrap
是基於Boostrap
使用的。
第二行安裝Reactstrap
及React
相關套件以利使用。
2. 載入Bootstrap CSS及產生Button
[程式碼]
- 載入Bootstrap CSS
// src/containers/Home/Home.jsimport 'bootstrap/dist/css/bootstrap.css';
因為Reactstrap
在許多Component都會用到,所以在最上層的Component載入即可,就不用每個Component都載入。
- 產生Button
// src/containers/Home/components/Content.jsimport { Button } from 'reactstrap';...<Button color="danger">danger</Button>
我們先加入<Button>
,確認是否套用成功。
要使用Reactstrap
的步驟:
- import載入要用的Component
- render中加入Component
此時畫面應該會出現一顆紅色的danger按鈕。
3. Grid System Go!!
[程式碼]
Bootstrap
另一個特點就是Grid System,它將畫面切成12等份,可以自行定義DOM元件要佔幾等份。
此特點用來做出響應式網頁(RWD)非常方便。
// Bootstrap 4<div class="container">
<div class="row">
<div class="col">
1 of 2
</div>
<div class="col">
1 of 2
</div>
</div>
<div class="row">
<div class="col">
1 of 3
</div>
<div class="col">
1 of 3
</div>
<div class="col">
1 of 3
</div>
</div>
</div>
先前有提到,Bootstrap
使用CSS設定,而Reactstrap
將其做成Component使用,因此我們將Grid System
使用到專案中。
// src/containers/Home/components/Content.jsimport { Button, Container, Row, Col } from 'reactstrap';...<Container>
<Row>
<Col xs="12" md="4"><Button color="danger" block>Danger</Button></Col>
<Col xs="12" md="4"><Button color="danger" block>Danger</Button></Col>
<Col xs="12" md="4"><Button color="danger" block>Danger</Button></Col>
<Col xs="12" md="4"><Button color="danger" block>Danger</Button></Col>
<Col xs="12" md="4"><Button color="danger" block>Danger</Button></Col>
<Col xs="12" md="4"><Button color="danger" block>Danger</Button></Col>
<Col xs="12" md="4"><Button color="danger" block>Danger</Button></Col>
<Col xs="12" md="4"><Button color="danger" block>Danger</Button></Col>
</Row>
</Container>
上面程式碼中,我們載入了<Container>
, <Row>
, <Col>
等Grid System
元件。
並加入8顆<Button>
,使用xs
md
來設定按鈕在對應的畫面尺寸下佔螢幕幾等份。
同學現在將瀏覽器畫面進行縮放,就會看到響應式網頁的效果囉!
4. 加入Jumbotron
[程式碼]
我們加入Jumbotron進行商店介紹,可設定標題及副標題。
// src/containers/Home/components/Content.jsimport { Container, Row, Col, Jumbotron, Button } from 'reactstrap';...<Col md={12}>
<Jumbotron>
<h1 className="display-3">美客唱片</h1>
<p className="lead">
美客唱片成立以來,結合實體唱片通路、唱片公司、網站,因而擁有豐富、完整的音樂資源
</p>
<p className="lead">
並與電視、廣播等媒體進行策略聯盟,已迅速打響知名度,並廣受各界好評
</p>
<p className="lead">
不僅如此,美客唱片將跨足大中華地區,透過舉辦跨國、跨區域的大型頒獎典禮、演唱會以及音樂活動
</p>
<p className="lead">
進一步擴大影響力,提昇流行音樂產業的動能
</p>
<hr className="my-2" />
<p className="lead">
<Button color="primary">購物車</Button>
</p>
</Jumbotron>
</Col>
一樣的,我們需要先載入<Jumbotron>
,並加入商店介紹的文字(自行發揮)及購物車按鈕。
5. 使用Card Component呈現商品資訊
[程式碼]
好的,此步驟就要做出商品資訊囉,我們採用的是<Card>
進行呈現。
// src/containers/Home/components/Content.jsimport { Container, Row, Col, Jumbotron, Button, Card, CardImg, CardBlock, CardTitle, CardSubtitle, CardText, Badge } from 'reactstrap';...<Row>
<Col sm={6} md={4} className="mb-3">
<Card>
<CardImg width="100%" src="https://placeholdit.imgix.net/~text?txtsize=33&txt=318%C3%97180&w=318&h=180" alt="Card image cap" />
<CardBlock>
<CardTitle>商品名稱</CardTitle>
<CardSubtitle>
<h4><Badge color="success">售價:1000</Badge></h4>
</CardSubtitle>
<CardText>商品描述</CardText>
<Button color="secondary">購買</Button>
</CardBlock>
</Card>
</Col>
</Row>
因為<Card>
需要用到的Component比較多,因此先載入多個Component。
商品資訊頁我們呈現的有圖片、商品名稱、售價、商品描述、購買按鈕。
6. 載入商品資訊json並使用map render商品資訊
[程式碼]
- 商品資訊json
我們使用json檔案模擬API收到後端回傳資訊,先在同一層資料夾中產生Album.json
,內容如下:
[json內容]
- 載入json檔案且使用state儲存商品資訊
// src/containers/Home/components/Content.jsimport AlbumJson from './Album.json';export default class Content extends Component {
state = {
album: AlbumJson,
}
render() {
const { album } = this.state;
...
}
}
使用import並指定json路徑來載入,AlbumJson
就是json的內容喔。
我們新增一個album
的state來存放商品資訊,並在render時取出來使用。
- map render 商品資訊
這裡使用Javascript中Array map來回傳含有多個Component的Array來render畫面。
// src/containers/Home/components/Content.js{
album.map(product => (
<Col sm={6} md={4} className="mb-3">
<Card>
<CardImg width="100%" src={product.img} alt="Card image cap" />
<CardBlock>
<CardTitle>{product.title}</CardTitle>
<CardSubtitle>
<h4>
{
product.discount
? <Badge color="danger">特價:{product.price}</Badge>
: <Badge color="success">售價:{product.price}</Badge>
}
</h4>
</CardSubtitle>
<CardText>{product.desc}</CardText>
<Button color="secondary">購買</Button>
</CardBlock>
</Card>
</Col>
))
}
React的render中要使用變數或撰寫程式碼必須使用{}
將其包起來執行,因此我們先以{}
作為開頭撰寫map
。
map
回傳的Component就是我們上個步驟做出來的<Card>
,只不過圖片、商品名稱、售價、商品描述等地方使用變數,所以使用{product.XXX}
將值呈現在畫面上。
// src/containers/Home/components/Content.js{
product.discount
? <Badge color="danger">特價:{product.price}</Badge>
: <Badge color="success">售價:{product.price}</Badge>
}
這裡會這樣寫是因為商品會有一個discount的屬性,當判斷discount為true時,使用紅色顯示特價,反之使用綠色顯示售價。
7. 購物車按鈕彈出Modal
[程式碼]
做到這裡,我們基本畫面都完成囉,現在要做的是點擊購物車按鈕後彈出Modal顯示購買物品。
我們使用的是Reactstrap的<Modal>
這裡比較複雜,我們分成多個步驟一一解釋:
- 載入Modal相關元件
// src/containers/Home/components/Content.jsimport { Container, Row, Col, Jumbotron, Button, Card, CardImg, CardBlock, CardTitle, CardSubtitle, CardText, Badge, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
- 加入Modal Component
// src/containers/Home/components/Content.js<Modal isOpen={this.state.modal} toggle={this.toggle}>
<ModalHeader toggle={this.toggle}>購物車</ModalHeader>
<ModalBody>
這裡要購買物品
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={this.toggle}>結帳</Button>{' '}
<Button color="secondary" onClick={this.toggle}>取消</Button>
</ModalFooter>
</Modal>
<Modal>
分成Heaer, Body, Footer等三個區塊。
Header
顯示購物車文字。
Body
顯示購買物品(下個步驟為最後步驟,會做出來)。
Footer
則擺放了結帳
及取消
按鈕
現在來解釋一下<Modal>
呈現的原理,我們可以看到第一行的props
isOpen={this.state.modal}
當isOpen=true時,<Modal>
會出現在畫面上,反之消失。
所以我們先加入一個state來存放<Modal>
顯示狀態。
- 加入modal state
每個Component都有自己的state
來存放資料,state
有兩個重點
- Component初始時就要宣告state。
- 要修改state就必須透過
setState
,才會觸發畫面更新。
// src/containers/Home/components/Content.jsstate = {
modal: false,
album: AlbumJson,
}
除了原本的album
外,多加一個modal
的state,預設為false,也就是<Modal>
預設不顯示在畫面上。
那我們該如何修改狀態呢?
我們想要達到的目標是點擊購物車按鈕就彈出<Modal>
。
所以在購物車按鈕加入onClick
事件來修改modal
狀態。
// src/containers/Home/components/Content.js<Button color="primary" onClick={this.toggle}>購物車</Button>
- 實作toggle function
// src/containers/Home/components/Content.jstoggle = () => {
this.setState({
modal: !this.state.modal,
});
}
上面有提到修改state
必須透過setState
進行修改。
觸發toggle
function後,設定modal為!this.state.modal,也就是說原本是true就變為false,false變為true,白話點就是開 -> 關,關 -> 開
現在點擊購物車按鈕,就會彈出<Modal>
囉。
8. 購物車中呈現購買物品
[程式碼]
同學辛苦囉,來到今天的最後一個步驟了,加油!
上個步驟我們使用<Modal>
彈出購物車畫面,而Body
中應該要顯示購買物品!
使用Reactstrap的<Table>
進行呈現
// src/containers/Home/components/Content.jsimport { Container, Row, Col, Jumbotron, Button, Card, CardImg, CardBlock, CardTitle, CardSubtitle, CardText, Badge, Modal, ModalHeader, ModalBody, ModalFooter, Table } from 'reactstrap';...<Table>
<thead>
<tr>
<th>#</th>
<th>品項</th>
<th>價格</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>300</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>150</td>
</tr>
<tr>
<th scope="row">3</th>
<td>Larry</td>
<td>900</td>
</tr>
</tbody>
</Table>
一樣的先載入<Table>
來使用,<Table>
和HTML原本的<table>
結構一樣,分成<thead>
和<tbody>
兩大區塊。
<thead>
中我們加入三個欄位顯示順序、品項及價格。
<tbody>
中依照這三個欄位顯示對應的資訊。
OK~我們已經使用Reactstrap將畫面呈現出來了!!
但目前購買物品資訊是假畫面,並未實作購買功能。
實作購買功能請期待Day 5
課程喔。