[7天學會ReactJS] Day4. 製作購物車畫面 -Reactstrap

Andy Tsai
ReactMaker
Published in
17 min readSep 12, 2017

同學們好,今天我們要來套用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使用的。

第二行安裝ReactstrapReact相關套件以利使用。

2. 載入Bootstrap CSS及產生Button

[程式碼]

  1. 載入Bootstrap CSS
// src/containers/Home/Home.jsimport 'bootstrap/dist/css/bootstrap.css';

因為Reactstrap在許多Component都會用到,所以在最上層的Component載入即可,就不用每個Component都載入。

  1. 產生Button

[Reactstrap — 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使用到專案中。

[Reactstrap — Layout]

// 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進行商店介紹,可設定標題及副標題。

[Reactstrap — 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>進行呈現。

[Reactstrap — 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商品資訊

[程式碼]

  1. 商品資訊json

我們使用json檔案模擬API收到後端回傳資訊,先在同一層資料夾中產生Album.json,內容如下:

[json內容]

  1. 載入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時取出來使用。

  1. map render 商品資訊

Array — map

這裡使用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>

[Reactstrap — Modal]

這裡比較複雜,我們分成多個步驟一一解釋:

  1. 載入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';
  1. 加入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>顯示狀態。

  1. 加入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>
  1. 實作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>進行呈現

[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課程喔。

--

--