cisen / blog

Time waits for no one.
134 stars 20 forks source link

antd pro 好东西学习 #179

Open cisen opened 5 years ago

cisen commented 5 years ago

项目的主要流程

入门

路由和菜单

路由和菜单是组织起一个应用的关键骨架,pro 中的路由为了方便管理,使用了中心化的方式,在 router.config.js 统一配置和管理。

基本结构

在这一部分,脚手架通过结合一些配置文件、基本算法及工具函数,搭建好了路由和菜单的基本框架,主要涉及以下几个模块/功能:

布局

页面整体布局是一个产品最外层的框架结构,往往会包含导航、页脚、侧边栏、通知栏以及内容等。在页面之中,也有很多区块的布局结构。在真实项目中,页面布局通常统领整个应用的界面,有非常重要的作用。

Ant Design Pro 的布局 Ant Design 布局组件 Ant Design Pro 的布局# 在 Ant Design Pro 中,我们抽离了使用过程中的通用布局,都放在 layouts 目录中,分别为:

Ant Design 布局组件

除了 Pro 里的内建布局以外,在一些页面中需要进行布局,可以使用 Ant Design 目前提供的两套布局组件工具:Layout 和 Grid。

Grid 组件

栅格布局是网页中最常用的布局,其特点就是按照一定比例划分页面,能够随着屏幕的变化依旧保持比例,从而具有弹性布局的特点。

而 Ant Design 的栅格组件提供的功能更为强大,能够设置间距、具有支持响应式的比例设置,以及支持 flex 模式,基本上涵盖了大部分的布局场景,详情参看:Grid。

Layout 组件

如果你需要辅助页面框架级别的布局设计,那么 Layout 则是你最佳的选择,它抽象了大部分框架布局结构,使得只需要填空就可以开发规范专业的页面整体布局,详情参看:Layout。

根据不同场景区分抽离布局组件

在大部分场景下,我们需要基于上面两个组件封装一些适用于当下具体业务的组件,包含了通用的导航、侧边栏、顶部通知、页面标题等元素。例如 Ant Design Pro 的 BasicLayout。

通常,我们会把抽象出来的布局组件,放到跟 pages、 components 平行的 layouts 文件夹中方便管理。需要注意的是,这些布局组件和我们平时使用的其它组件并没有什么不同,只不过功能性上是为了处理布局问题。

业务组件

于一些可能被多处引用的功能模块,建议提炼成业务组件统一管理。这些组件一般有以下特征:

样式

这篇文档主要针对如何在项目中使用和规划样式文件进行介绍,如果想获取基础的 CSS 知识或查阅属性,可以参考 MDN文档

less

Ant Design Pro 默认使用 less 作为样式语言,建议在使用前或者遇到疑问时学习一下 less 的相关特性。

CSS Modules

在样式开发过程中,有两个问题比较突出:

为了解决上述问题,我们的脚手架默认使用 CSS Modules 模块化方案,先来看下在这种模式下怎么写样式。

// example.js
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;
}

用 less 写样式好像没什么改变,只是类名比较简单(实际项目中也是这样),js 文件的改变就是在设置 className 时,用一个对象属性取代了原来的字符串,属性名跟 less 文件中对应的类名相同,对象从 less 文件中引入。

在上面的样式文件中,.title 只会在本文件生效,你可以在其他任意文件中使用同名选择器,也不会对这里造成影响。不过有的时候,我们就是想要一个全局生效的样式呢?可以使用 :global。

// 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>

类名被自动添加了一个 hash 值,这保证了它的唯一性。 除了上面的基础知识,还有一些关键点需要注意:

上面只对 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。

src/utils/utils.less

这里可以放置一些工具函数供调用,比如清除浮动 .clearfix。

模块样式

针对某个模块/页面生效的文件。

通用模块级

例如 src/layouts/BasicLayout.less,里面包含一些基本布局的样式,被 src/layouts/BasicLayout.js 引用,项目中使用这种布局的页面就不需要再关心整体布局的设置。如果你的项目中需要使用其他布局,也建议将布局相关的 js 和 less 放在这里 src/layouts。

页面级

具体页面相关的样式,例如 src/routes/Dashborad/Monitor.less,里面的内容仅和本页面的内容相关。一般情况下,如果不是页面内容特别复杂,有了前面全局样式、通用模块样式的配合,这里要写的应该不多。

组件级

这个也很简单,就是组件相关的样式了,有一些在页面中重复使用的片段或相对独立的功能,你可以提炼成组件,相关的样式也应该提炼出来放在组件中,而不是混淆在页面里。

以上样式类别都是针对独立的样式文件,有时样式配置特别简单,也没有重复使用,你也可以用内联样式 style={{ ... }} 来设置。

覆盖组件样式

由于业务的个性化需求,我们经常会遇到需要覆盖组件样式的情况,这里举个简单的例子。

antd Select 在多选状态下,默认会展示所有选中项,这里我们给它加一个限制高度,超过此高度就出滚动条。

// TestPage.js
import { Select } from 'antd';
import styles from './TestPage.less'
const Option = Select.Option;

const children = [];
for (let i = 10; i < 36; i++) {
  children.push(<Option key={i.toString(36) + i}>{i.toString(36) + i}</Option>);
}

ReactDOM.render(
  <Select
    mode="multiple"
    style={{ width: 300 }}
    placeholder="Please select"
    className={styles.customSelect}
  >
    {children}
  </Select>
, mountNode);
// TestPage.less
.customSelect {
  :global {
    .ant-select-selection {
      max-height: 51px;
      overflow: auto;
    }
  }
}

方法很简单,有两点需要注意:

引入的 antd 组件类名没有被 CSS Modules 转化,所以被覆盖的类名 .ant-select-selection 必须放到 :global 中。

因为上一条的关系,覆盖是全局性的。为了防止对其他 Select 组件造成影响,所以需要包裹额外的 className 限制样式的生效范围。

cisen commented 5 years ago

进阶

业务图标

通常情况下,你可以通过 Ant Design 提供的 图标组件来使用 Ant Design 官方图标。基本使用方式如下:

<Icon type="heart" style={{ fontSize: '16px', color: 'hotpink' }} />

如果你没有在 Ant Design 官方图标中找到需要的图标,可以到 iconfont.cn 上采集并生成自己的业务图标库,再进行使用。

一、生成图标库代码

首先,搜索并找到你需要的图标,将它采集到你的购物车里,在购物车里,你可以将选中的图标添加到项目中(没有的话,新建一个),后续生成的资源/代码都是以项目为维度的。

如果你已经有了设计稿,只是需要生成相关代码,可以上传你的图标后,再进行上面的操作。

账户相关布局

来到刚才选中的项目页,点击『生成代码』的链接,会在下方生成不同引入方式的代码,下面会分别介绍。

账户相关布局

二、引入

有三种引入方式供你选择:SVG Symbol、Unicode 及 Font class。我们推荐在现代浏览器下使用 SVG Symbol 方式引入。

SVG Symbol

SVG 符号引入是现代浏览器未来主流的图标引入方式。其方法是预先加载符号,在合适的地方引入并渲染为矢量图形。有如下特点:

一般使用步骤如下:

  1. 切换到 Symbol 页签,复制项目生成的地址代码:
    //at.alicdn.com/t/font_405362_lyhvoky9rc7ynwmi.js
  2. 加入图标样式代码,如果没有特殊的要求,你可以直接复用 Ant Design 图标的样式
    .icon {
    width: 1em;
    height: 1em;
    fill: currentColor;
    vertical-align: -.125em;
    }

    挑选相应图标并获取类名,应用于页面

    <svg class="icon" aria-hidden="true">
    <use xlink:href="#icon-ali-pay"></use>
    </svg>

    你也可以通过使用 Ant Design 图标组件提供的 Icon.createFromIconfontCN({...}) 方法来更加方便地使用图标,使用方式如下:

配置项目地址,创建图标组件。详细用法

import { Icon } from 'antd';

const IconFont = Icon.createFromIconfontCN({
  scriptUrl: '//at.alicdn.com/t/font_405362_lyhvoky9rc7ynwmi.js'
});

export default IconFont;

之后可以像使用 <Icon /> 组件一样方便地使用,支持配置样式

<IconFont type="icon-ali-pay" style={{ fontSize: '16px', color: 'lightblue' }} />

Unicode

这是最原始的方式,需要三步来完成引入:

拷贝项目生成的字体库代码,你可以新建一个样式文件来放置图标相关的样式。

@font-face {
  font-family: 'iconfont';
  src: url('//at.alicdn.com/t/font_405362_lyhvoky9rc7ynwmi.eot');
  src: url('//at.alicdn.com/t/font_405362_lyhvoky9rc7ynwmi.eot?#iefix') format('embedded-opentype'),
  url('//at.alicdn.com/t/font_405362_lyhvoky9rc7ynwmi.woff') format('woff'),
  url('//at.alicdn.com/t/font_405362_lyhvoky9rc7ynwmi.ttf') format('truetype'),
  url('//at.alicdn.com/t/font_405362_lyhvoky9rc7ynwmi.svg#iconfont') format('svg');
}

加入图标样式代码,如果没有特殊的要求,你可以直接复用 Ant Design 图标的样式。

.iconfont {
  display: inline-block;
  font-style: normal;
  vertical-align: baseline;
  text-align: center;
  text-transform: none;
  line-height: 1;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  &:before {
    display: block;
    font-family: "iconfont" !important;  /* 注意与 font-face 中的匹配 */
  }
}

在项目中鼠标移动到要用的图标上,点击『复制代码』,就得到了图标对应的字体编码,现在可以直接引入了:

<i class="iconfont">&#xe66b;</i>

Font Class

这种方式只是在上一种方式的基础上,给每个图标对应设置了一个语义化的类名,方便使用及后期维护。

切换到 Font class 页签,在页面头部引入下面生成的 css 代码:

//at.alicdn.com/t/font_405362_lyhvoky9rc7ynwmi.css

如果不喜欢标签引入的方式,也可以直接拷贝上面链接中的代码到你的样式文件中。如果不喜欢网站默认生成的类名,自己重写这部分代码即可,比如:

- .icon-ali-pay:before { content: "\e66b"; }              // 修改前
+ .monitor-icon-alipay:before { content: "\e66b"; }       // 修改后

这时你可以选择拷贝图标对应代码(就是类名,如果类名被重写过,这里记得用修改后的),直接使用:

<i class="iconfont icon-ali-pay"></i>

不过我们更推荐将它封装一下:

import React from 'react';

const BizIcon = (props) => {
  const { type } = props;
  return <i className={`iconfont icon-${type}`} />;
};
export default BizIcon;

现在可以更加方便地使用:

<BizIcon type="ali-pay" />

Unicode 和 Font Class 本质上就是字体,你可以通过一些字体的样式属性去控制这种图标的展现,同时浏览器兼容性很好,但不支持多色图标。

相关内容可以参考: iconfont.cn 代码使用帮助 Web 设计新趋势: 使用 SVG 代替 Web Icon Font