ant-design 简单学习,记录一下。
ant-design-pro官网v4 附带开发手册 效果预览
umi脚手架
因为umi是阿里工具,所以使用tyarn安装。
# 安装
$ yarn global add umi
# 更新umi
yarn global upgrade umi
项目初始化
# 新建应用
yarn create umi project_name
选择 antd 、 dva 、js、npm
新建页面
export default () => {
return <div>hello world</div>;
}
外部可以引用
import React from 'react';
class ShoppingList extends React.Component {
constructor(props) {
super(props);
this.state = {
value: null,
};
}
componentDidMount() {
}
componentWillUnmount() {
}
componentDidUpdate() {
}
render() {
const picture = {
src: 'https://cdn.nlark.com/yuque/0/2018/jpeg/84141/1536207007004-59352a41-4ad8-409b-a416-a4f324eb6d0b.jpeg',
};
return (
<div className="shopping-list">
<h1>Shopping List for {this.props.name}</h1>
<ul>
<li>Instagram</li>
<li>WhatsApp</li>
<li>Oculus</li>
</ul>
</div>
);
}
}
export default ShoppingList;
路由
routes: [
{
path: '/user',
component: '../layouts/UserLayout',
routes: [
{
name: 'login',
path: '/user/login',
component: './user/login',
},
{
name: 'UserDashboard',
icon: 'smile',
path: '/user-dashboard',
component: './user-dashboard',
},
],
},
{
path: '/',
component: '../layouts/SecurityLayout',
routes: [
{
path: '/',
component: '../layouts/BasicLayout',
authority: ['admin', 'user'],
routes: [
{
path: '/',
redirect: '/welcome',
},
{
path: '/welcome',
name: 'welcome',
icon: 'smile',
component: './Welcome',
},
{
name: '监控页',
icon: 'smile',
path: '/dashboardmonitor1',
component: './DashboardMonitor',
},
{
component: './404',
},
],
},
{
component: './404',
},
],
},
{
component: './404',
},
],
布局
import { Layout } from 'antd';
const { Header, Footer, Sider, Content } = Layout;
ReactDOM.render(
<div>
<Layout>
<Header>Header</Header>
<Content>Content</Content>
<Footer>Footer</Footer>
</Layout>
<Layout>
<Sider>Sider</Sider>
<Layout>
<Header>Header</Header>
<Content>Content</Content>
<Footer>Footer</Footer>
</Layout>
</Layout>
</div>,
mountNode,
);
栅格
import { Row, Col } from 'antd';
ReactDOM.render(
<div>
<Row>
<Col span={12}>col-12</Col>
<Col span={12}>col-12</Col>
</Row>
<Row>
<Col span={8}>col-8</Col>
<Col span={8}>col-8</Col>
<Col span={8}>col-8</Col>
</Row>
</div>,
mountNode,
);
示例
效果:
结构:
index.jsx
页面元素
import React from 'react';
import { connect } from 'dva';
import { Table, Modal, Button, Form, Input } from 'antd';
import SampleChart from '../../components/SampleChart';
const FormItem = Form.Item;
class List extends React.Component {
state = {
visible: false,
statisticVisible: false,
id: null,
};
columns = [
{
title: '名称',
dataIndex: 'name',
},
{
title: '描述',
dataIndex: 'desc',
},
{
title: '链接',
dataIndex: 'url',
render: value => <a href={value}>{value}</a>,
},
{
title: '',
dataIndex: 'statistic',
render: (_, { id }) => {
return (
<Button onClick={() => { this.showStatistic(id); }}>图表</Button>
);
},
},
];
showModel = () => {
this.setState({ visible: true })
};
handleCancel = () => {
this.setState({
visible: false,
});
};
handleStatisticCancel = () => {
this.setState({
statisticVisible: false,
});
};
showStatistic = (id) => {
this.props.dispatch({
type: 'cards/getStatistic',
payload: id,
});
this.setState({ id, statisticVisible: true });
};
handleOk = () => {
const { dispatch, form: { validateFields } } = this.props;
validateFields((err, values) => {
if (!err) {
dispatch({
type: 'cards/addOne',
payload: values,
});
// 重置 `visible` 属性为 false 以关闭对话框
this.setState({ visible: false });
}
});
};
componentDidMount() {
this.props.dispatch({
type: 'cards/queryList',
});
}
render() {
const { visible, statisticVisible, id } = this.state;
const { cardsList, cardsLoading, form: { getFieldDecorator }, statistic } = this.props;
return (
<div>
<Table columns={this.columns} dataSource={cardsList} loading={cardsLoading} rowKey="id"/>
<Button onClick={this.showModel}>新建</Button>
<Modal title="新建记录"
visible={visible}
onOk={this.handleOk}
onCancel={this.handleCancel}
>
<Form>
<FormItem label="名称">
{getFieldDecorator('name', {
rules: [{ required: true }],
})(
<Input/>
)}
</FormItem>
<FormItem label="描述">
{getFieldDecorator('desc')(
<Input/>
)}
</FormItem>
<FormItem label="链接">
{getFieldDecorator('url', {
rules: [{ type: 'url' }],
})(
<Input/>
)}
</FormItem>
</Form>
</Modal>
<Modal visible={statisticVisible} footer={null} onCancel={this.handleStatisticCancel}>
<SampleChart data={statistic[id]} />
</Modal>
</div>
);
}
}
function mapStateToProps(state) {
return {
cardsList: state.cards.cardsList,
cardsLoading: state.loading.effects['cards/queryList'],
statistic: state.cards.statistic,
};
}
export default connect(mapStateToProps)(Form.create()(List));
model.js
页面所有方法
import * as service from './service';
export default {
namespace: 'cards',
state: {
cardsList: [],
statistic: {},
},
effects: {
* queryList({ payload }, { call, put }) {
const rsp = yield call(service.queryList, payload);
yield put({
type: 'initList',
payload: { cardsList: rsp.result }
});
},
*deleteOne({ payload }, { call, put }) {
const rsp = yield call(service.deleteOne, payload);
return rsp;
},
*addOne({ payload }, { call, put }) {
const rsp = yield call(service.addOne, payload);
yield put({ type: 'queryList' });
return rsp;
},
*getStatistic({ payload }, { call, put }) {
const rsp = yield call(service.getStatistic, payload);
yield put({
type: 'saveStatistic',
payload: {
id: payload,
data: rsp.result,
},
});
return rsp;
},
},
reducers: {
initList(state, { payload: { cardsList } }) {
return {
...state,
cardsList
};
},
saveStatistic(state, { payload: { id, data } }) {
return {
...state,
statistic: {
...state.statistic,
[id]: data,
},
}
},
}
};
service.js
所有异步请求
import request from '@/utils/request';
export function queryList() {
return request('/api/cards');
}
export function deleteOne(id) {
return request(`/api/cards/${id}`, {
method: 'DELETE'
});
}
export function addOne(data) {
return request('/api/cards/add', {
headers: {
'content-type': 'application/json',
},
method: 'POST',
body: JSON.stringify(data),
});
}
export function getStatistic(id) {
return request(`/api/cards/${id}/statistic`);
}
_mock.js
模拟数据
let data = [
{
id: 1,
name: 'umi',
desc: '极快的类 Next.js 的 React 应用框架。',
url: 'https://umijs.org'
},
{
id: 2,
name: 'antd',
desc: '一个服务于企业级产品的设计体系。',
url: 'https://ant.design/index-cn'
},
{
id: 3,
name: 'antd-pro',
desc: '一个服务于企业级产品的设计体系。',
url: 'https://ant.design/index-cn'
}
];
export default {
'get /api/cards': function (req, res, next) {
setTimeout(() => {
res.json({
result: data,
})
}, 250)
},
'delete /api/cards/:id': function (req, res, next) {
data = data.filter(v => v.id !== parseInt(req.params.id));
console.log(req.params.id);
console.log(data);
setTimeout(() => {
res.json({
success: true,
})
}, 250)
},
'post /api/cards/add': function (req, res, next) {
data = [...data, {
...req.body,
id: data[data.length - 1].id + 1,
}];
res.json({
success: true,
});
},
'get /api/cards/:id/statistic': function (req, res, next) {
res.json({
result: [
{ genre: 'Sports', sold: 275 },
{ genre: 'Strategy', sold: 1150 },
{ genre: 'Action', sold: 120 },
{ genre: 'Shooter', sold: 350 },
{ genre: 'Other', sold: 150 },
]
});
},
}
附带一个 SampleChart
import React from 'react';
import G2 from '@antv/g2';
class SampleChart extends React.Component {
constructor(props) {
super(props);
this.containerRef = React.createRef();
}
componentDidMount() {
this.chart = new G2.Chart({
container: this.containerRef.current,
width: 450,
height: 300
});
this.refreshChart();
}
componentDidUpdate(prevProps) {
if (prevProps.data !== this.props.data) {
this.refreshChart();
}
}
componentWillUnmount() {
if (this.chart) {
this.chart.destroy();
}
}
refreshChart = () => {
this.chart.source(this.props.data);
this.chart.interval().position('genre*sold').color('genre');
this.chart.render();
};
render() {
return (
<div ref={this.containerRef} />
);
}
}
export default SampleChart;
表单操作
数据绑定:
const [noteForm] = Form.useForm();
<Form
{...layout}
name="basic"
initialValues={{}}
onFinish={updatePushUrl}
form={noteForm}
// onFinishFailed={onFinishFailed}
>
<Form.Item
label="提醒地址"
name="noteUrl"
>
<Input/>
</Form.Item>
<Form.Item {...tailLayout}>
<Button type="primary" htmlType="submit">
提交
</Button>
</Form.Item>
</Form>
赋值
noteForm.setFieldsValue({"noteUrl": res.data});
提交
const updatePushUrl = (values: PushChange) => {
service.updatePushUrl(values);
}