3 -【 Ant Design 】

1 什么是 Ant Design?

Ant Design 是阿里蚂蚁金服团队基于 React 开发的 ui 组件,主要用于后台系统的使用。

官网:https://ant.design/index-cn

在这里插入图片描述

设计语言:

随着商业化的趋势,越来越多的企业级产品对更好的用户体验有了进一步的要求。 带着这样的一个终极目标,我们(蚂蚁金服体验技术部)经过大量的项目实践和总结,逐步打磨出一个服务于企业级产品的设计体系 Ant Design。基于『确定』和 『自然』的设计价值观,通过模块化的解决方案,降低冗余的生产成本,让设计者专注于更好的用户体验。

特性:

  • 提炼自企业级中后台产品的交互语言和视觉风格。
  • 开箱即用的高质量 React 组件。
  • 使用 TypeScript 构建,提供完整的类型定义文件。
  • 全链路开发和设计工具体系。

2 开始使用

2.1 引入 Ant Design

Ant Design 是一个服务于企业级产品的设计体系,组件库是它的 React 实现,antd 被发布为一个 npm 包方便开发者安装并使用。

在 umi 中,你可以通过在插件集 umi-plugin-react 中配置 antd 打开 antd 插件,antd 插件会帮你引入 antd 并实现按需编译。

config.js 文件中进行配置:

export default {
    plugins: [
        ['umi-plugin-react', {
            dva: true, // 开启dva功能
            antd: true // 开启Ant Design功能
        }]
    ]
};

在这里插入图片描述

2.2 小试牛刀

接下来,我们开始使用 antd 的组件,以 tabs 组件为例,地址:https://ant.design/components/tabs-cn/

效果:

在这里插入图片描述

看下官方给出的使用示例:

import { Tabs } from 'antd';

const { TabPane } = Tabs;

function callback(key) {
  console.log(key);
}

ReactDOM.render(
  <Tabs defaultActiveKey="1" onChange={callback}>
    <TabPane tab="Tab 1" key="1">
      Content of Tab Pane 1
    </TabPane>
    <TabPane tab="Tab 2" key="2">
      Content of Tab Pane 2
    </TabPane>
    <TabPane tab="Tab 3" key="3">
      Content of Tab Pane 3
    </TabPane>
  </Tabs>,
  mountNode,
);

下面我们参考官方给出的示例,进行使用:

创建 MyTabs.js 文件:

import React from 'react';
import { Tabs } from 'antd'; // 第一步:导入需要使用的组建

const { TabPane } = Tabs;

function callback(key) {
    console.log(key);
}

class MyTabs extends React.Component {

    render() {
        return (
            <Tabs defaultActiveKey="1" onChange={callback}>
                <TabPane tab="Tab 1" key="1">
                    Content of Tab Pane 1
                </TabPane>
                <TabPane tab="Tab 2" key="2">
                    Content of Tab Pane 2
                </TabPane>
                <TabPane tab="Tab 3" key="3">
                    Content of Tab Pane 3
                </TabPane>
            </Tabs>
        );
    }
}

export default MyTabs;

在这里插入图片描述

效果:

在这里插入图片描述

到此,我们已经掌握了 antd 组件的基本使用。

2.3 布局

antd 布局:https://ant.design/components/layout-cn/ 在后台系统页面布局中,往往是经典的三部分布局,像这样:

在这里插入图片描述

下面,我们通过 antd 组件来完成这个布局。

2.3.1 组件概述

  • Layout : 布局容器,其下可嵌套 Header Sider Content FooterLayout 本身,可以放在任何父容器中。

  • Header : 顶部布局,自带默认样式,其下可嵌套任何元素,只能放在 Layout 中。

  • Sider : 侧边栏,自带默认样式及基本功能,其下可嵌套任何元素,只能放在 Layout 中。

  • Content : 内容部分,自带默认样式,其下可嵌套任何元素,只能放在 Layout 中。

  • Footer : 底部布局,自带默认样式,其下可嵌套任何元素,只能放在 Layout 中。

2.3.2 搭建整体框架

index.js 是整个项目的全局布局文件。

src 目录下创建 layouts 目录,并且在 layouts 目录下创建 index.js文件,写入内容:

import React from 'react'
import { Layout } from 'antd';

const { Header, Footer, Sider, Content } = Layout;

class BasicLayout extends React.Component{
    render(){
        return (
            <Layout>
                <Sider>Sider</Sider>
                <Layout>
                    <Header>Header</Header>
                    <Content>Content</Content>
                    <Footer>Footer</Footer>
                </Layout>
            </Layout>
        );
    }
}

export default BasicLayout;

需要特别说明的是,在umi中约定的目录结构中,layouts/index.js 文件将被作为全局的布局文件。

接下来,配置路由: (非必须)

config.js 文件:

export default {
    plugins: [
        ['umi-plugin-react', {
            dva: true, // 开启dva功能
            antd: true // 开启Ant Design功能
        }]
    ],
    routes: [{
        path: '/',
        component: '../layouts' //配置布局路由
    }]
};

在这里插入图片描述

进行页面访问:

在这里插入图片描述

可以看到,布局已经生成,只是样式优点丑。

2.3.3 子页面使用布局

前面所定义的布局是全局布局,那么,在子页面中如何使用这个全局布局呢?

首先,需要在布局文件中,将 Content 内容替换成 {this.props.children},意思是引入传递的内容。

在这里插入图片描述

接下来配置路由(注意,在布局路由下面进行配置):

说明: 下面的路由配置,是表明你需要通过手动配置的方式上进行访问页面,而不采用umi默认的路由方式

下面作为了解,以后学习:

export default {
plugins: [
  ['umi-plugin-react', {
      dva: true, // 开启dva功能
      antd: true // 开启Ant Design功能
  }]
],
routes: [{
  path: '/',
  component: '../layouts', // 配置布局路由
  routes: [ // 在这里进行配置子页面
      {
          path: '/myTabs',
          component: './myTabs'
      }
  ]
}]
};

在这里插入图片描述

进行访问测试:

在这里插入图片描述

可以看到,在 MyTabs 组件中已经应用了全局的布局。其他子页面也就同理了。

2.3.4 美化页面

接下来,对页面做一些美化的工作:

import React from 'react'
import { Layout } from 'antd';

const { Header, Footer, Sider, Content } = Layout;

class BasicLayout extends React.Component{
    render(){
        return (
            <Layout>
                <Sider width={256} style={{ minHeight: '100vh', color: 'white' }}>
                        Sider
                </Sider>
                <Layout>
                    <Header style={{ background: '#fff', textAlign: 'center', padding: 0 }}>Header</Header>

                    <Content style={{ margin: '24px 16px 0' }}>
                        <div style={{ padding: 24, background: '#fff', minHeight: 360 }}>
                            {
                                this.props.children
                            }
                        </div>
                    </Content>

                    <Footer style={{ textAlign: 'center' }}>后台系统 ©2018 Created by XXX</Footer>
                </Layout>
            </Layout>
        );
    }
}

export default BasicLayout;

在这里插入图片描述

效果:

在这里插入图片描述

2.3.5 引入导航条

使用Menu组件作为导航条:https://ant.design/components/menu-cn/

import React from 'react'
import { Layout, Menu, Icon } from 'antd';

const { Header, Footer, Sider, Content } = Layout;
const SubMenu = Menu.SubMenu;

class BasicLayout extends React.Component{

    constructor(props){
        super(props);
        this.state = {
            collapsed: false,
        }
    }

    render(){
        return (
            <Layout>
                <Sider width={256} style={{minHeight: '100vh', color: 'white'}}>
                    <div style={{ height: '32px', background: 'rgba(255,255,255,.2)', margin: '16px'}}/>
                    <Menu
                        defaultSelectedKeys={['2']}
                        defaultOpenKeys={['sub1']}
                        mode="inline"
                        theme="dark"
                        inlineCollapsed={this.state.collapsed}
                    >
                        <Menu.Item key="1">
                            <Icon type="pie‐chart"/>
                            <span>Option 1</span>
                        </Menu.Item>
                        <Menu.Item key="2">
                            <Icon type="desktop"/>
                            <span>Option 2</span>
                        </Menu.Item>
                        <Menu.Item key="3">
                            <Icon type="inbox"/>
                            <span>Option 3</span>
                        </Menu.Item>
                        <SubMenu key="sub1" title={<span><Icon type="mail"/><span>Navigation One</span></span>}>
                            <Menu.Item key="5">Option 5</Menu.Item>
                            <Menu.Item key="6">Option 6</Menu.Item>
                            <Menu.Item key="7">Option 7</Menu.Item>
                            <Menu.Item key="8">Option 8</Menu.Item>
                        </SubMenu>
                        <SubMenu key="sub2" title={<span><Icon type="appstore"/><span>Navigation Two</span></span>}>
                            <Menu.Item key="9">Option 9</Menu.Item>
                            <Menu.Item key="10">Option 10</Menu.Item>
                            <SubMenu key="sub3" title="Submenu">
                                <Menu.Item key="11">Option 11</Menu.Item>
                                <Menu.Item key="12">Option 12</Menu.Item>
                            </SubMenu>
                        </SubMenu>
                    </Menu>
                </Sider>
                <Layout>
                    <Header style={{background: '#fff', textAlign: 'center', padding: 0}}>Header</Header>

                    <Content style={{margin: '24px 16px 0'}}>
                        <div style={{padding: 24, background: '#fff', minHeight: 360}}>
                            {
                                this.props.children
                            }
                        </div>
                    </Content>
                    <Footer style={{textAlign: 'center'}}>后台系统 ©2018 Created by XXX</Footer>
                </Layout>
            </Layout>
        );
    }
}

export default BasicLayout;

在这里插入图片描述

效果:

在这里插入图片描述

2.3.6 为导航添加链接

下面,我们对左侧的导航条添加链接,点击相应的链接在右侧进行相应页面的显示。

src 目录下创建 user 目录,并且在 user 目录下创建 UserAdd.jsUserList.js 文件,用于模拟实现新增用户和查询用户列表功能。

  • 先删除页面布局,只保留一个菜单

    在这里插入图片描述

  • 创建新增用户和查询用户列表页面:

    在这里插入图片描述

    UserAdd.js:

    import React from 'react'
    
    class UserAdd extends React.Component{
    
        render(){
            return (
                <div>新增用户</div> );
        }
    }
    
    export default UserAdd;
    

    UserList.js:

    import React from 'react'
    
    class UserList extends React.Component{
    
        render(){
            return (
                <div>用户列表</div> );
        }
    }
    
    export default UserList;
    
  • 为菜单添加链接:
    方式一:使用 <a>href
    在这里插入图片描述

    方式二:使用 umilink,先引入 link

    在这里插入图片描述

注意: 这里使用了umi的link标签,目的是出现记录点击的菜单。

2.4 表格

2.4.1 基本用法

参考官方文档进行实现:https://ant.design/components/table-cn/

改造 UserList.js 页面:

import React from 'react'
import {Table, Divider, Tag, Pagination } from 'antd';

const { Column } = Table;

const data = [{
    key: '1',
    name: '张三',
    age: 32,
    address: '上海市',
    tags: ['程序员', '帅气'],
}, {
    key: '2',
    name: '李四', age: 42,
    address: '北京市', tags: ['屌丝'],
}, {
    key: '3',
    name: '王五',
    age: 32,
    address: '杭州市',
    tags: ['高富帅', '富二代'],
}];

class UserList extends React.Component {
    render() {
        return (
            <div>
                <Table dataSource={data} pagination={{position:"bottom",total:500,pageSize:10, defaultCurrent:3}}>
                    <Column title="姓名" dataIndex="name" key="name"/>
                    <Column title="年龄" dataIndex="age" key="age"/>
                    <Column title="地址" dataIndex="address" key="address"/>
                    <Column title="标签" dataIndex="tags" key="tags"
                            render={tags => (
                                <span>
                                    {tags.map(tag => <Tag color="blue" key={tag}>{tag}</Tag>)}
                                </span>
                            )}
                    />
                    <Column title="操作"
                            key="action"
                            render={(text, record) => (
                                <span>
                                    <a href="javascript:;">编辑</a>
                                    <Divider type="vertical"/>
                                    <a href="javascript:;">删除</a>
                                </span>
                            )}
                    />
                </Table>
            </div>
        );
    }
}

export default UserList;

在这里插入图片描述

2.4.2 将数据分离到 model 中

model 的实现:

UserListData.js

import request from "../util/request";

export default {
    namespace: 'userList',
    state: {
        list: []
    },
    effects: {
        *initData(params, sagaEffects) {
            const {call, put} = sagaEffects;
            const url = "/ds/user/list";
            let data = yield call(request, url);
            yield put({
                type : "queryList",
                data : data
            });
        } },
    reducers: {
        queryList(state, result) {
            let data = [
                ...result.data];
            return { // 更新状态值
                list: data
            }
        }
    }
}

修改 UserList.js 中的逻辑:

import React from 'react'
import {Table, Divider, Tag, Pagination } from 'antd';
import { connect } from 'dva';

const { Column } = Table;

const namespace = 'userList';

@connect((state)=>{
    return {
        data : state[namespace].list
    }
}, (dispatch) => {
    return {
        initData : () => {
            dispatch({
                type: namespace + "/initData"
            });
        }
    }
})
class UserList extends React.Component {
    componentDidMount(){
        this.props.initData();
    }

    render() {
        return (
            <div>
                <Table dataSource={this.props.data} pagination={{position:"bottom",total:500,pageSize:10, defaultCurrent:3}}>
                    <Column title="姓名" dataIndex="name" key="name"/>
                    <Column title="年龄" dataIndex="age" key="age"/>
                    <Column title="地址" dataIndex="address" key="address"/>
                    <Column title="标签" dataIndex="tags" key="tags"
                            render={tags => (
                                <span>
                                    {tags.map(tag => <Tag color="blue" key={tag}>{tag}</Tag>)}
                                </span>
                            )}
                    />
                    <Column title="操作"
                            key="action"
                            render={(text, record) => (
                                <span>
                                    <a href="javascript:;">编辑</a>
                                    <Divider type="vertical"/>
                                    <a href="javascript:;">删除</a>
                                </span>
                            )}
                    />
                </Table>
            </div>
        );
    }
}

export default UserList;

mock 数据:MockListData.js

export default {
    'get /ds/list': function (req, res) {
        res.json({
            data: [1, 2, 3, 4],
            maxNum: 4
        }); },
    'get /ds/user/list': function (req, res) {
        res.json([{
            key: '1',
            name: '张三1',
            age: 32,
            address: '上海市',
            tags: ['程序员', '帅气'],
        }, {
            key: '2',
            name: '李四', age: 42,
            address: '北京市', tags: ['屌丝'],
        }, {
            key: '3',
            name: '王五',
            age: 32,
            address: '杭州市',
            tags: ['高富帅', '富二代'],
        }]);
    }
}

测试结果:

在这里插入图片描述

发布了675 篇原创文章 · 获赞 214 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/weixin_42112635/article/details/104826656