前言:以下內容基於React全家桶+AntD實戰課程的學習實踐過程記錄。最終成果github地址:https://github.com/66Web/react-antd-manager,歡迎star。
一、按鈕Button

- pages->ui->button.js:對應路由/admin/ui/buttons
import React from 'react';
import {Card, Button, Radio} from 'antd'
import './ui.less'
class Buttons extends React.Component{
state = {
loading: true,
size: 'default'
}
handleCloseLoading = () =>{
this.setState({
loading: false
})
}
handleChange = (e) => {
this.setState({
size: e.target.value
})
}
render(){
return(
<div>
<Card title="基礎按鈕" className="card-wrap">
<Button type="primary">提交</Button>
<Button>普通</Button>
<Button type="dashed">非重要功能</Button>
<Button type="danger">刪除</Button>
<Button disabled>禁用</Button>
</Card>
<Card title="圖形按鈕" className="card-wrap">
<Button icon="plus">創建</Button>
<Button icon="edit">編輯</Button>
<Button icon="delete">刪除</Button>
<Button shape="circle" icon="search"></Button>
<Button type="primary" icon="search">搜索</Button>
<Button type="primary" icon="download">下載</Button>
</Card>
<Card title="Loading按鈕" className="card-wrap">
<Button type="primary" loading={this.state.loading}>確定</Button>
<Button type="primary" shape="circle" loading={this.state.loading}></Button>
<Button loading={this.state.loading} >點擊加載</Button>
<Button shape="circle" loading={this.state.loading}></Button>
<Button type="primary" onClick={this.handleCloseLoading}>關閉</Button>
</Card>
<Card title="按鈕組" style={{marginBottom:10}}>
<Button.Group>
<Button type="primary" icon="left">返回</Button>
<Button type="primary" icon="right">前進</Button>
</Button.Group>
</Card>
<Card title="按鈕尺寸" className="card-wrap">
<Radio.Group size={this.state.size} onChange={this.handleChange}>
<Radio value="small">小</Radio>
<Radio value="default">中</Radio>
<Radio value="large">大</Radio>
</Radio.Group>
<Button type="primary" size={this.state.size}>Imooc</Button>
<Button size={this.state.size}>Imooc</Button>
<Button type="dashed" size={this.state.size}>Imooc</Button>
<Button type="danger" size={this.state.size}>Imooc</Button>
</Card>
</div>
);
}
}
export default Buttons;
- Button組件
- type屬性 :表示按鈕類型
- disable屬性:表示禁用按鈕
- icon屬性:表示按鈕圖標樣式 icon圖標集合
- shape屬性:表示按鈕形狀(circle表示圓形)
- loading屬性:為{true}表示加載中(此時按鈕不能點擊)
- size屬性:表示組件大小
- Button.Group按鈕組組件:表示包含的Button組件是一個組
- Card組件
- title屬性用於標注卡片上方標題
- Radio組件
- 外部需要用Radio.Group組件包裹
- 通過外部組件對象可以獲得內部Radio組件的value值(通過
e.target.value)
- 坑:Route頁面內容超過屏幕時,會出現滾動條,左側下方出現空白區
- 解決:ui.less中給main添加overflow:auto; 當渲染頁面高度超過當前屏幕時,自動滾動
二、彈框Modal

- pages->ui->modals:對應路由/admin/ui/modals
import React from 'react';
import {Card, Button, Modal} from 'antd'
import './ui.less'
export default class Buttons extends React.Component{
state = {
showModal1: false,
showModal2: false,
showModal3: false,
showModal4: false
}
handleOpen = (type) => {
this.setState({
[type]: true
})
}
handleConfirm = (type) => {
Modal[type]({
title: '確認?',
content:'你確認你學會了React了嗎?',
onOk() {
console.log('ok')
},
onCancel() {
console.log('Cancel')
}
})
}
render(){
return (
<div>
<Card title="基礎模態框" className="card-wrap">
<Button type="primary" onClick={() => this.handleOpen('showModal1')}>Open</Button>
<Button type="primary" onClick={() => this.handleOpen('showModal2')}>自定義頁腳</Button>
<Button type="primary" onClick={() => this.handleOpen('showModal3')}>頂部20px頁腳</Button>
<Button type="primary" onClick={() => this.handleOpen('showModal4')}>水平垂直居中</Button>
</Card>
<Card title="信息確認框" className="card-wrap">
<Button type="primary" onClick={() => this.handleConfirm('confirm')}>Confirm</Button>
<Button type="primary" onClick={() => this.handleConfirm('info')}>Info</Button>
<Button type="primary" onClick={() => this.handleConfirm('success')}>Success</Button>
<Button type="primary" onClick={() => this.handleConfirm('warning')}>Warning</Button>
</Card>
<Modal
title="React"
visible={this.state.showModal1}
onCancel={() => {
this.setState({
showModal1: false
})
}}>
<p>歡迎使用柳柳版彈框</p>
</Modal>
<Modal
title="React"
visible={this.state.showModal2}
okText="好的"
cancelText="算了"
onCancel={() => {
this.setState({
showModal2: false
})
}}>
<p>歡迎使用柳柳版彈框</p>
</Modal>
<Modal
title="React"
style={{top:20}}
visible={this.state.showModal3}
onCancel={() => {
this.setState({
showModal3: false
})
}}>
<p>歡迎使用柳柳版彈框</p>
</Modal>
<Modal
title="React"
wrapClassName="vertical-center-modal"
visible={this.state.showModal4}
onCancel={() => {
this.setState({
showModal4: false
})
}}>
<p>歡迎使用柳柳版彈框</p>
</Modal>
</div>
)
}
}
- Modal組件
- title屬性:作為標題顯示
- visible屬性:參數為
{true|false},為true則顯示,false則不顯示 - onCancel屬性:值為一個函數,執行當點擊模態框的×或cancel選項時執行的方法
- Model內部填寫的內容將作為模態框的正文內容
- Model自定義頁腳實現方式
- visible屬性:{true}或{false}實現是否顯示
- okText屬性:設置OK選項的顯示內容
- cancelText屬性:設置Cancel選項顯示內容
- Model頂部20px彈框實現方式
- style屬性:值為{{top:20}}設定距頂部20px
- Model水平居中實現方式
- 利用Model組件的wrapClassName設定樣式名稱
- React監聽事件方法時手動綁定this
- 除了使用xxx.bind(this)外,直接使用箭頭函數定義方法會自動綁定this到當前React實例上
handleConfirm = (type) => { Modal[type]({ title: '確認?', content:'你確認你學會了React了嗎?', onOk() { console.log('ok') }, onCancel() { console.log('Cancel') } }) }
- React事件調用方法並傳參
- onClick事件內容若為this.handleConfirm('confirm')表示一開始就會自動調用,無法傳參;
- 當需要傳參時,需要將onClick中的內容變為:箭頭函數返回代參的調用方法,從而實現點擊時執行函數並傳參調用方法
onClick={() => this.handleConfirm('confirm')} -
傳遞的參數如果想作為對象的鍵時,需要用
[]進行包裹,如果沒包裹直接放置鍵的位置則視為變量而報錯
三、加載中Spin
- pages->ui->loadings:對應路由/admin/ui/loadings
import React from 'react';
import {Card, Spin, Icon, Alert} from 'antd'
import './ui.less'
export default class Loadings extends React.Component{
render() {
const icon = <Icon type="loading" style={{fontSize:24}}/>
return (
<div>
<Card title="Spin用法" className="card-wrap">
<Spin size="small"/>
<Spin style={{margin:'0 10px'}}/>
<Spin size="large"/>
<Spin indicator={icon} style={{marginLeft:10}}/>
</Card>
<Card title="內容遮罩" className="card-wrap">
<Alert
message="React"
description="歡迎使用柳柳版信息框"
type="info"
/>
<Spin>
<Alert
message="React"
description="歡迎使用柳柳版警告框"
type="warning"
/>
</Spin>
<Spin tip="加載中">
<Alert
message="React"
description="歡迎使用柳柳版警告框"
type="warning"
/>
</Spin>
<Spin indicator={icon}>
<Alert
message="React"
description="歡迎使用柳柳版警告框"
type="warning"
/>
</Spin>
</Card>
</div>
)
}
}
- Spin組件
- indicator屬性:加載指定的圖標indicator={icon}
const icon = <Icon type="loading"/>; <Spin indicator={icon}/> - size屬性:設置大小
- tip屬性:當作為包裹元素時,可以自定義描述文案
tip:"加載中"
- style={{fontSize:24}} 調整顯示圖標的大小
- 樣式注意
- style={{marginLeft:10}},marginLeft:xx ,xx是數字可以省略px
- 如果是style={{margin:'0 10px'}},xx 是字符串的情況,則不能省略px
- Alert組件
- type屬性:表示提示的樣式,有四種選擇 success、info、warning、error
- message屬性:表示提示內容(設置標題信息)
- description屬性:表示提示的輔助性文字介紹(設置具體描述的內容)
- 任意組件蒙板加載效果
- <Spin>組件內嵌套自閉合組件(如<Alert />)
四、通知提醒Notification
- pages->ui->notice.js:對應路由/admin/ui/notification
import React from 'react';
import {Card, Button, notification} from 'antd'
import './ui.less'
export default class Notice extends React.Component{
openNotification = (type, direction) => {
if(direction){
notification.config({
placement: direction
})
}
notification[type]({
message:'發工資了',
description:'上個月考勤22天,遲到12天,實發工資2500,請笑納'
})
}
render(){
return (
<div>
<Card title="通知提醒" className="card-wrap">
<Button type="primary" onClick={() => this.openNotification('success')}>Success</Button>
<Button type="primary" onClick={() => this.openNotification('info')}>Info</Button>
<Button type="primary" onClick={() => this.openNotification('warning')}>Warning</Button>
<Button type="primary" onClick={() => this.openNotification('error')}>Error</Button>
</Card>
<Card title="自定義方向位" className="card-wrap">
<Button type="primary" onClick={() => this.openNotification('success','topLeft')}>Success</Button>
<Button type="primary" onClick={() => this.openNotification('info','topRight')}>Info</Button>
<Button type="primary" onClick={() => this.openNotification('warning','bottomLeft')}>Warning</Button>
<Button type="primary" onClick={() => this.openNotification('error','bottomRight')}>Error</Button>
</Card>
</div>
)
}
}
- Notification組件Api
- notification.success(config)
- notification.error(config)
- notification.info(config)
- notification.warning(config)
- notification.warn(config)
- Notification組件Config
- message參數:表示通知提醒標題
- description參數:表示通知提醒內容
- placement參數:表示彈出位置(可選)
- Notification全局配置方法
notification.config(options)- 在調用前提前配置,全局一次生效
openNotification = (type, direction) => { if(direction){ notification.config({ placement: direction }) } notification[type]({ message:'發工資了', description:'上個月考勤22天,遲到12天,實發工資2500,請笑納' }) }
五、全局提示框Message

- pages->ui->messages:對應路由/admin/ui/messages
import React from 'react';
import {Card, Button, message} from 'antd'
import './ui.less'
export default class Messages extends React.Component{
showMessage = (type) => {
message[type]("恭喜你,React課程晉級成功");
}
render(){
return (
<div>
<Card title="全局提示框" className="card-wrap">
<Button type="primary" onClick={() => this.showMessage('success')}>Success</Button>
<Button type="primary" onClick={() => this.showMessage('info')}>Info</Button>
<Button type="primary" onClick={() => this.showMessage('warning')}>Warning</Button>
<Button type="primary" onClick={() => this.showMessage('loading')}>Loading</Button>
</Card>
</div>
)
}
}
- Message組件Api
- message.success(content, [duration], onClose)
- message.error(content, [duration], onClose)
- message.info(content, [duration], onClose)
- message.warning(content, [duration], onClose)
- message.loading(content, [duration], onClose)
- Message組件Config
- content屬性:表示提示內容
- duration屬性:表示自動關閉的延時,單位秒(設為 0 時不自動關閉)
- onClose方法:關閉時觸發的回調函數
六、頁簽Tab

- pages->ui->tabs.js:對應路由/admin/ui/tabs
import React from 'react';
import {Card, Tabs, message, Icon} from 'antd'
import './ui.less'
const TabPane = Tabs.TabPane;
export default class Tab extends React.Component{
handleCallBack = (key) => {
message.info("Hi,您選擇了頁簽:"+key)
}
componentWillMount(){
this.newTabIndex = 0;
const panes = [
{
title: 'Tab 1',
content: '歡迎使用柳柳版頁簽',
key: '1'
},
{
title: 'Tab 2',
content: '歡迎使用柳柳版頁簽',
key: '2'
},
{
title: 'Tab 3',
content: '歡迎使用柳柳版頁簽',
key: '3'
}
]
this.setState({
panes,
activeKey: panes[0].key
})
}
onChange = (activeKey) => {
this.setState({
activeKey
})
}
//onEdit、add、remove直接從官網復制過來即可
onEdit = (targetKey, action) => {
this[action](targetKey);
}
add = () => {
const panes = this.state.panes;
const activeKey = `newTab${this.newTabIndex++}`;
panes.push({ title: activeKey, content: 'Content of new Tab', key: activeKey });
this.setState({ panes, activeKey });
}
//activeKey:當前激活的key, targetKey:當前刪除的Key
remove = (targetKey) => {
let activeKey = this.state.activeKey;
let lastIndex;
this.state.panes.forEach((pane, i) => {
if (pane.key === targetKey) {
lastIndex = i - 1;
}
});
const panes = this.state.panes.filter(pane => pane.key !== targetKey);
if (lastIndex >= 0 && activeKey === targetKey) {
activeKey = panes[lastIndex].key;
}
this.setState({ panes, activeKey });
}
render() {
return (
<div>
<Card title="Tab頁簽" className="card-wrap">
<Tabs defaultActiveKey="1" onChange={this.handleCallBack}>
<TabPane tab="Tab 1" key="1">歡迎使用柳柳版頁簽</TabPane>
<TabPane tab="Tab 2" key="2" disabled>歡迎使用柳柳版頁簽</TabPane>
<TabPane tab="Tab 3" key="3">歡迎使用柳柳版頁簽</TabPane>
</Tabs>
</Card>
<Card title="Tab帶圖的頁簽" className="card-wrap">
<Tabs defaultActiveKey="1" onChange={this.handleCallBack}>
<TabPane tab={<span><Icon type="plus" />增加</span>} key="1">歡迎使用柳柳版頁簽</TabPane>
<TabPane tab={<span><Icon type="edit" />編輯</span>} key="2">歡迎使用柳柳版頁簽</TabPane>
<TabPane tab={<span><Icon type="delete" />刪除</span>} key="3">歡迎使用柳柳版頁簽</TabPane>
</Tabs>
</Card>
<Card title="Tab動態的頁簽" className="card-wrap">
<Tabs
onChange={this.onChange}
activeKey={this.state.activeKey}
type="editable-card"
onEdit={this.onEdit}
>
{
this.state.panes.map((panel) => {
return <TabPane
tab = {panel.title}
key = {panel.key}
>{panel.content}</TabPane>
})
}
</Tabs>
</Card>
</div>
)
}
}
- Tabs組件
- type屬性:頁簽的基本樣式
- activeKey屬性:當前激活頁簽的key
- defaultActiveKey屬性:初始化選中面板的 key,如果沒有設置 activeKey
- hideAdd屬性:是否隱藏加號圖標,在
type="editable-card"時有效 - onChange方法:切換面板的回調
- onEdit方法:新增和刪除頁簽的回調,在
type="editable-card"時有效
-
Tabs.TabPane
- 頁簽面板:使用Tabs組件時必須先初始化TabPane
const TabPane = Tabs.TabPane;
-
tab屬性:選項卡頭顯示文字
-
key屬性:對應activeKey
-
forceRender屬性:被隱藏時是否渲染 DOM 結構
- Tabs帶圖頁簽
- 指定圖標:用Icon組件
- 注意:JSX語法,{}根對象中不能直接同時套用<Icon />和文字,外層必須包裹一個根元素<span></span>
tab={<span><Icon type="plus" />增加</span>
-
Tabs動態頁簽
-
JS變量循環顯示:定義生命周期方法componentWillMount執行
-
type="editable-card":指定樣式為可編輯的卡片樣式 -
onChange事件:設置頁簽改變時調用方法,設置激活的key
- onEdit、add、remove方法:直接從官網復制過來即可
七、畫廊gallery

- pages->ui->gallery:對應路由/admin/ui/gallery
import React from 'react';
import {Card, Row, Col, Modal} from 'antd'
import './ui.less'
export default class Gallery extends React.Component{
state = {
visible: false
}
openGallery = (imgSrc) => {
this.setState({
visible: true,
currentImg: '/gallery/'+imgSrc
})
}
render(){
const imgs = [
['1.png','2.png','3.png','4.png','5.png'],
['6.png','7.png','8.png','9.png','10.png'],
['11.png','12.png','13.png','14.png','15.png'],
['16.png','17.png','18.png','19.png','20.png'],
['21.png','22.png','23.png','24.png','25.png']
]
const imgList = imgs.map((list) => list.map((item) =>
<Card
style={{marginBottom:10}}
cover={<img src={'/gallery/'+item} onClick={() => this.openGallery(item)}/>}
>
<Card.Meta
title="React Admin"
description="66 Elena gallery"
/>
</Card>
))
return (
<div className="card-wrap">
<Row gutter={10}>
<Col md={5}>
{imgList[0]}
</Col>
<Col md={5}>
{imgList[1]}
</Col>
<Col md={5}>
{imgList[2]}
</Col>
<Col md={5}>
{imgList[3]}
</Col>
<Col md={4}>
{imgList[4]}
</Col>
</Row>
<Modal
width={300}
height={500}
visible={this.state.visible}
title="圖片畫廊"
onCancel={() => {
this.setState({
visible: false
})
}}
footer={null}
>
{<img src={this.state.currentImg} style={{width:'100%'}}/>}
</Modal>
</div>
)
}
}
- Card組件
- cover屬性:卡片封面
-
Card.Meta
- 使Card組件支持更靈活的內容:靈活內容
- title屬性:表示標題內容
- description屬性:表示描述內容
- 柵格布局區塊間隔
- 關鍵:
Row的gutter屬性,常使用(16+8n)px作為左右間隙(n為自然數) - Col 使用樣式設置間隙:style={{ marginBottom: 10}}
<Card style={{marginBottom:10}} cover={<img src={'/gallery/'+item} onClick={() => this.openGallery(item)}/>} > <Card.Meta title="React Admin" description="66 Elena gallery" /> </Card>
-
點擊查看大圖
-
onClick點擊事件:使用箭頭函數,傳遞 item
-
關閉底部按鈕:footer={null}
-
設置Modal寬高:width={300} height={500}
-
控制Modal顯示:設置
visible,onCancel
八、輪播Carousel
- pages->ui->carousel:對應路由/admin/ui/carousel
import React from 'react';
import {Card, Carousel} from 'antd'
import './ui.less'
export default class Carousels extends React.Component{
render(){
return (
<div>
<Card title="文字背景輪播" className="card-wrap">
<Carousel autoplay effect="fade">
<div><h3>Ant Motion Banner - React</h3></div>
<div><h3>Ant Motion Banner - Vue</h3></div>
<div><h3>Ant Motion Banner - Angular</h3></div>
</Carousel>
</Card>
<Card title="圖片輪播" className="card-wrap slider-wrap">
<Carousel autoplay>
<div><img src="/carousel-img/carousel-1.jpg"/></div>
<div><img src="/carousel-img/carousel-2.jpg"/></div>
<div><img src="/carousel-img/carousel-3.jpg"/></div>
</Carousel>
</Card>
</div>
)
}
}
- Carousel組件
- vertical屬性:表示是否垂直顯示
- dots屬性:表示是否顯示面板指示點
- autoplay屬性:表示是否自動切換
- easing屬性:表示動態效果
- effect屬性:表示動畫效果函數
- beforeChange:切換面板的回調
- afterChange:切換面板的回調
- 圖片輪播
- autoplay:設置自動切換
- effect="fade":指定淡入淡出動畫,不指定默認為scalex動畫
- 輪播組件開始並沒有顯示:需要引入官網demo的樣式或自定義樣式
/* Carousel For demo */ .ant-carousel .slick-slide { text-align: center; height: 160px; line-height: 160px; background: #364d79; overflow: hidden; } .ant-carousel .slick-slide h3 { color: rgba(246, 250, 33, 0.966); } - 自定義樣式:修改圖片的默認高度,!important設置優先級
// 圖片輪播 .slider-wrap .ant-carousel .slick-slide { height: 240px!important; }
九、路由及樣式
- router.js:配置Admin組件的子路由
import React from 'react'
import {HashRouter, Route, Switch} from 'react-router-dom'
import App from './App'
import Login from './pages/Login'
import NoMatch from './pages/NoMatch'
import Admin from './admin'
import Home from './pages/Home'
import Buttons from './pages/ui/buttons'
import Modals from './pages/ui/modals'
import Loadings from './pages/ui/loadings'
import Notice from './pages/ui/notice'
import Messages from './pages/ui/messages'
import Tabs from './pages/ui/tabs'
import Gallery from './pages/ui/gallery'
import Carousel from './pages/ui/carousel'
export default class IRouter extends React.Component{
render() {
return (
<HashRouter>
<App>
<Route path="/login" component={Login}></Route>
<Route path="/admin" render={() =>
<Admin>
<Switch>
<Route path="/admin/home" component={Home}></Route>
<Route path="/admin/ui/buttons" component={Buttons}></Route>
<Route path="/admin/ui/modals" component={Modals}></Route>
<Route path="/admin/ui/loadings" component={Loadings}></Route>
<Route path="/admin/ui/notification" component={Notice}></Route>
<Route path="/admin/ui/messages" component={Messages}></Route>
<Route path="/admin/ui/tabs" component={Tabs}></Route>
<Route path="/admin/ui/gallery" component={Gallery}></Route>
<Route path="/admin/ui/carousel" component={Carousel}></Route>
<Route component={NoMatch}></Route>
</Switch>
</Admin>
}></Route>
<Route path="/order/detail" component={Login}></Route>
</App>
</HashRouter>
)
}
}
- pages->ui->ui.less:設置ui目錄下所有組件的樣式
.card-wrap{
margin-bottom: 10px;
button{
margin-right: 10px;
}
}
/* modals */
/* use css to set position of modal */
.vertical-center-modal {
text-align: center;
white-space: nowrap;
}
.vertical-center-modal:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
width: 0;
}
.vertical-center-modal .ant-modal {
display: inline-block;
vertical-align: middle;
top: 0;
text-align: left;
}
/* Carousel For demo */
.ant-carousel .slick-slide {
text-align: center;
height: 160px;
line-height: 160px;
background: #364d79;
overflow: hidden;
}
.ant-carousel .slick-slide h3 {
color: rgba(246, 250, 33, 0.966);
}
// 圖片輪播
.slider-wrap .ant-carousel .slick-slide {
height: 240px!important;
}
注:項目來自慕課網
