antd pro学习笔记(一)

antd procss

页面管理

路由

antd中路由由config.ts统一管理html

配置#

咱们在 config.ts 扩展了一些关于 pro 全局菜单的配置。前端

{
  name: 'dashboard',
  icon: 'dashboard',
  hideInMenu: true,
  hideChildrenInMenu: true,
  hideInBreadcrumb: true,
  authority: ['admin'],
}
  • name: 当前路由在菜单和面包屑中的名称,注意这里是国际化配置的 key,具体展现菜单名能够在 /src/locales/zh-CN.ts 进行配置。
  • icon: 当前路由在菜单下的图标名。
  • hideInMenu: 当前路由在菜单中不展示,默认 false
  • hideChildrenInMenu: 当前路由的子级在菜单中不展示,默认 false
  • hideInBreadcrumb: 当前路由在面包屑中不展示,默认 false
  • authority: 容许展现的权限,不设则均可见,详见

菜单

根据config.ts自动生成react

不须要菜单,能够在 src/layouts/BasicLayout.tsx 中设置 menuRender={false}]()git

从服务器请求菜单

src/layouts/BasicLayout.tsx 中修改 menuDataRender,在代码中发起 http 请求github

代码以下(BasicLayout.tsx与返回的meduData):web

BasicLayout.tsxexpress

const [menuData, setMenuData] = useState([]);

useEffect(() => {
  // 这里是一个演示用法
  // 真实项目中建议使用 dva dispatch 或者 umi-request
  fetch('/api/example.json')
    .then(response => response.json())
    .then(data => {
      setMenuData(data || []);
    });
}, []);

...

return (
  <ProLayout
    // ...
    menuDataRender={() => menuData}
    // ...
  />
);

返回的menuData(返回数据中的path须要在config.ts中定义):npm

[
  {
    "path": "/dashboard",
    "name": "dashboard",
    "icon": "dashboard",
    "children": [
      {
        "path": "/dashboard/analysis",
        "name": "analysis",
        "exact": true
      },
      {
        "path": "/dashboard/monitor",
        "name": "monitor",
        "exact": true
      },
      {
        "path": "/dashboard/workplace",
        "name": "workplace",
        "exact": true
      }
    ]
  }
  // ....
]

面包屑

经过menuRender方法实现点击逻辑json

<ProLayout
      logo={logo}
      onCollapse={handleMenuCollapse}
      menuItemRender={(menuItemProps, defaultDom) => (
        <Link to={menuItemProps.path}>{defaultDom}</Link>
      )}
      ...
      ...
   />

新增页面

在config.ts中routes下增长一个路径:

// 路由配置
  routes: [
    {
      path: '/',
      component: '../layouts/BasicLayout',
      Routes: ['src/pages/Authorized'],
      authority: ['admin', 'user'],
      routes: [
        {
          path: '/',
          name: 'welcome',
          icon: 'smile',
          component: './Welcome',
        },
      ],
    },
  ],

上述代码中的component属性是用来肯定布局的

(在antd中脚手架有两种默认的布局:基础布局 - BasicLayout 以及 帐户相关布局 - UserLayout

也能够在routes属性下的component中设置每一个页面的布局方式

umi

管理路由的框架(可插拔的企业级 react 应用框架)

更多详细内容请参见:umi#路由

跳转页面

经过如下代码来跳转到这个路由:

import router from 'umi/router';

router.push('/dashboard/anyParams');

//or

import Link from 'umi/link';

<Link to="/dashboard/anyParams">go</Link>;

———————————————

Ant Design 布局组件

Ant Design 目前提供两个布局:LayoutGrid

Grid组件

栅格布局,又称弹性布局,主要特色是弹性

Layout组件

更偏向于设计页面总体的布局

——————————————

区块

一些项目中常常会用到的典型页面的模板

  • 之前开发一个页面:建立 JS -> 建立 CSS -> 建立 Model -> 建立 service -> 写页面组件。
  • 如今开发一个页面:下载区块 -> 基于区块初始化好的页面组件修改代码。

Ant Design Pro 中,使用 umi 进行区块管理:

用umi block list 命令来查看区块

添加区块:umi block add [block url]

添加区块到对应路由

umi block add ant-design-pro/analysis --path=your/path/here

--path 参数指定路由

add 后面是区块名或区块路径

区块开发,能够在 umi 区块 中查看完整内容。

——————————————

新增页面

1.写js/less文件

在antd中,颜色什么的尽可能使用antd给的默认变量

@import '~antd/lib/style/themes/default.less;

2.将文件加入菜单和路由#

3.写model和service文件

——————————————

复用组件

复用组件通常有如下特征:

  • 只负责一块相对独立,稳定的功能;
  • 多是纯静态的,也可能包含本身的 state,但不涉及 dva 的数据流,仅受父组件(一般是一个页面)传递的参数控制。
  • 没有单独的路由配置;

写复用组件通常步骤:

这里最好看antd pro的官方例子:https://pro.ant.design/docs/new-component-cn

——————————————

antd中样式怎么写

使用css modules来管理样式

在css modules模式下怎么写样式:

// example.ts
import styles from './example.less';
export default ({ title }) => <div className={styles.title}>{title}</div>;
// example.less .title {
  color: @heading-color;
  font-weight: 600;
  margin-bottom: 16px;
}

js 文件的改变就是在设置 className 时,用一个对象属性(上述例子中的styles.title)取代了原来的字符串,属性名跟 less 文件中对应的类名相同,对象从 less 文件中引入。

设置全局样式

// example.less
/* 定义本文件中的样式 */
.title {
  color: @heading-color;
  font-weight: 600;
  margin-bottom: 16px;
}

/* 定义单个全局样式 */
:global(.text) {
  font-size: 16px;
}

/* 定义多个全局样式 */
:global {
  .footer {
    color: #ccc;
  }
  .sider {
    background: #ebebeb;
  }
}

CSS Modules 的原理:

对每一个类名(非 :global 声明的)按照必定规则进行转换,保证它的惟一性。

若是在浏览器里查看这个示例的 dom 结构,你会发现实际渲染出来是这样的:

<div class="title___3TqAx">title</div>

注意:

CSS Modules 只会对 className 以及 id 进行转换,其余的好比属性选择器,标签选择器都不进行处理,推荐尽可能使用 className。

上面只对 CSS Modules 进行了最基础的介绍,有兴趣能够参考其余文档:

全局样式文件

src/index.less#

全局样式文件,在这里你能够进行一些通用设置,好比脚手架中自带的:

html, body, :global(#root) {
  height: 100%;
}

body {
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

// temporary font size patch :global(.ant-tag) {
  font-size: 12px;
}

由于 antd 中会自带一些全局设置,如字号,颜色,行高等,因此在这里,你只须要关注本身的个性化需求便可,不用进行大量的 reset。

——————————————

覆盖组件样式#

例子:

覆盖antd中select组件的样式:

// TestPage.less
.customSelect {
:global {
.ant-select-selection {
max-height: 51px;
overflow: auto;
}
}
}
  • 引入的 antd 组件类名没有被 CSS Modules 转化,因此被覆盖的类名 .ant-select-selection 必须放到 :global 中。
  • 由于上一条的关系,覆盖是全局性的。为了防止对其余 Select 组件形成影响,因此须要包裹额外的 className 限制样式的生效范围。

——————————————

引入外部模块

引入依赖#

在终端输入下面的命令完成安装:

$ npm install react-quill --save

加上 --save 参数会自动添加依赖到 package.json 中去。

使用#

直接贴代码了:

import React from 'react';
import { Button, notification, Card } from 'antd';
import ReactQuill from 'react-quill';
import 'react-quill/dist/quill.snow.css';

export default class NewPage extends React.Component {
  state = {
    value: 'test',
  };

  handleChange = value => {
    this.setState({
      value,
    });
  };

  prompt = () => {
    notification.open({
      message: 'We got value:',
      description: <span dangerouslySetInnerHTML={{ __html: this.state.value }} />,
    });
  };

  render() {
    return (
      <Card title="富文本编辑器">
        <ReactQuill value={this.state.value} onChange={this.handleChange} />
        <Button style={{ marginTop: 16 }} onClick={this.prompt}>
          Prompt
        </Button>
      </Card>
    );
  }
}

富文本

这样就成功引入了一个富文本组件。有几点值得注意:

  • import 时须要注意组件暴露的数据结构;
  • 有一些组件须要额外引入样式,好比本例。

——————————————

Mock (前端模拟数据)和联调

使用 umi 的 mock 功能#

umi 里约定 mock 文件夹下的文件即 mock 文件,文件导出接口定义,支持基于 require 动态分析的实时刷新,支持 ES6 语法,以及友好的出错提示,详情参看 umijs.org

export default {
  // 支持值为 Object 和 Array
  'GET /api/users': { users: [1, 2] },

  // GET POST 可省略
  '/api/users/1': { id: 1 },

  // 支持自定义函数,API 参考 express@4
  'POST /api/users/create': (req, res) => {
    res.end('OK');
  },
};

当客户端(浏览器)发送请求,如:GET /api/users,那么本地启动的 umi dev 会跟此配置文件匹配请求路径以及方法,若是匹配到了,就会将请求经过配置处理,就能够像样例同样,你能够直接返回数据,也能够经过函数处理以及重定向到另外一个服务器。

引入 Mock.ts

Mock.ts 是经常使用的辅助生成模拟数据的第三方库,固然你能够用你喜欢的任意库来结合 umi 构建数据模拟功能。

import mockjs from 'mockjs';

export default {
  // 使用 mockjs 等三方库
  'GET /api/tags': mockjs.mock({
    'list|100': [{ name: '@city', 'value|1-100': 50, 'type|0-2': 1 }],
  }),
};

添加跨域请求头

设置 response 的请求头便可:

'POST /api/users/create': (req, res) => {
  ...
  res.setHeader('Access-Control-Allow-Origin', '*');
  ...
},

合理的拆分你的 mock 文件#

对于整个系统来讲,请求接口是复杂而且繁多的,为了处理大量模拟请求的场景,咱们一般把每个数据模型抽象成一个文件,统一放在 mock 的文件夹中,而后他们会自动被引入。

img

如何模拟延迟#

为了更加真实地模拟网络数据请求,每每须要模拟网络延迟时间。

手动添加 setTimeout 模拟延迟#

你能够重写请求的代理方法,在其中添加模拟延迟的处理,如:

'POST /api/forms': (req, res) => {
  setTimeout(() => {
    res.send('Ok');
  }, 1000);
},

使用插件模拟延迟#

上面的方法虽然简便,可是当你须要添加全部的请求延迟的时候,可能就麻烦了,不过能够经过第三方插件来简化这个问题,如:roadhog-api-doc#delay

import { delay } from 'roadhog-api-doc';

const proxy = {
  'GET /api/project/notice': getNotice,
  'GET /api/activities': getActivities,
  'GET /api/rule': getRule,
  'GET /api/tags': mockjs.mock({
    'list|100': [{ name: '@city', 'value|1-100': 50, 'type|0-2': 1 }],
  }),
  'GET /api/fake_list': getFakeList,
  'GET /api/fake_chart_data': getFakeChartData,
  'GET /api/profile/basic': getProfileBasicData,
  'GET /api/profile/advanced': getProfileAdvancedData,
  'POST /api/register': (req, res) => {
    res.send({ status: 'ok' });
  },
  'GET /api/notices': getNotices,
};

// 调用 delay 函数,统一处理
export default delay(proxy, 1000);

联调#

当本地开发完毕以后,若是服务器的接口知足以前的约定,那么只须要关闭 mock 数据或者代理到服务端的真实接口地址便可。

$ npm run start:no-mock

( 本文部分转自于antd pro官网)