第一部分: 前言
推薦網站: https://ant.design/docs/spec/introduce-cn
ant.design是基於react開發的一個解放ui和前端的工具,它提供了一致的設計方便我們快速開發和減少不必要的設計與代碼,很多實用react框架的開發者都已經在使用ant.design了,且其在github上的star數也早已上萬,足見其火熱程度。
ant.design的目的也在於提高用戶、開發者等多方的體驗與幸福感。
ant.design設計很精妙,vue的iview就是模仿ant.design來實現的。
既然要使用ant.design,我們不妨了解其設計原則是否是我們想要的,對於設計,我了解的最多的便是對比、對齊、親密性、重復性,而ant.design也很好的實現了這些規則,並在此基礎山踐行了更多的想法。
- 直接了當 『需要在哪里輸出,就要允許在哪里輸入』。這就是直接操作的原理。eg:不要為了編輯內容而打開另一個頁面,應該直接在上下文中實現編輯。
- 足不出戶
- 簡化交互 --- 如懸停時出現工具,qq在這里做的很好。
- 提供邀請
- 巧用過渡
https://ant.design/docs/spec/colors-cn
第二部分: 使用(引入css不好的方法)
ant.design 使用起來非常簡單。
第一步:
npm install antd --save
第二步(選擇性的):
將node_modules下面的dist下面的 antd.min.css 取出放在靜態文件中,在head中link引入。
第三步,開始使用:
在某個組件的上方:
import {message} from 'antd'
然后在需要的時候使用: message.error('錯誤'); message.success('登錄成功!'); 類似的使用即可。
如果我們僅僅是js,css完全自己寫,那么上面的就足夠了,但是,如果我們希望使用 ant.design 提供的css,那么我們就需要把css文件取出放在靜態文件中,並在html的head中引用了。
注意: 在使用的時候引入的css中還使用了css初始化,如下所示:

* antd v2.12.3 * * Copyright 2015-present, Alipay, Inc. * All rights reserved. */ /*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */ /* Document ========================================================================== */ /** * 1. Correct the line height in all browsers. * 2. Prevent adjustments of font size after orientation changes in * IE on Windows Phone and in iOS. */ html { line-height: 1.15; /* 1 */ -ms-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; /* 2 */ } /* Sections ========================================================================== */ /** * Remove the margin in all browsers (opinionated). */ body { margin: 0; } /** * Add the correct display in IE 9-. */ article, aside, footer, header, nav, section { display: block; } /** * Correct the font size and margin on `h1` elements within `section` and * `article` contexts in Chrome, Firefox, and Safari. */ h1 { font-size: 2em; margin: 0.67em 0; } /* Grouping content ========================================================================== */ /** * Add the correct display in IE 9-. * 1. Add the correct display in IE. */ figcaption, figure, main { /* 1 */ display: block; } /** * Add the correct margin in IE 8. */ figure { margin: 1em 40px; } /** * 1. Add the correct box sizing in Firefox. * 2. Show the overflow in Edge and IE. */ hr { box-sizing: content-box; /* 1 */ height: 0; /* 1 */ overflow: visible; /* 2 */ } /** * 1. Correct the inheritance and scaling of font size in all browsers. * 2. Correct the odd `em` font sizing in all browsers. */ pre { font-family: monospace, monospace; /* 1 */ /* stylelint-disable-line */ font-size: 1em; /* 2 */ } /* Text-level semantics ========================================================================== */ /** * 1. Remove the gray background on active links in IE 10. * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. */ a { background-color: transparent; /* 1 */ -webkit-text-decoration-skip: objects; /* 2 */ } /** * 1. Remove the bottom border in Chrome 57- and Firefox 39-. * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. */ abbr[title] { border-bottom: none; /* 1 */ text-decoration: underline; /* 2 */ text-decoration: underline dotted; /* 2 */ } /** * Prevent the duplicate application of `bolder` by the next rule in Safari 6. */ b, strong { font-weight: inherit; } /** * Add the correct font weight in Chrome, Edge, and Safari. */ b, strong { font-weight: bolder; } /** * 1. Correct the inheritance and scaling of font size in all browsers. * 2. Correct the odd `em` font sizing in all browsers. */ code, kbd, samp { font-family: monospace, monospace; /* 1 */ /* stylelint-disable-line */ font-size: 1em; /* 2 */ } /** * Add the correct font style in Android 4.3-. */ dfn { font-style: italic; } /** * Add the correct background and color in IE 9-. */ mark { background-color: #ff0; color: #000; } /** * Add the correct font size in all browsers. */ small { font-size: 80%; } /** * Prevent `sub` and `sup` elements from affecting the line height in * all browsers. */ sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sub { bottom: -0.25em; } sup { top: -0.5em; } /* Embedded content ========================================================================== */ /** * Add the correct display in IE 9-. */ audio, video { display: inline-block; } /** * Add the correct display in iOS 4-7. */ audio:not([controls]) { display: none; height: 0; } /** * Remove the border on images inside links in IE 10-. */ img { border-style: none; } /** * Hide the overflow in IE. */ svg:not(:root) { overflow: hidden; } /* Forms ========================================================================== */ /** * 1. Change the font styles in all browsers (opinionated). * 2. Remove the margin in Firefox and Safari. */ button, input, optgroup, select, textarea { font-family: sans-serif; /* 1 */ font-size: 100%; /* 1 */ line-height: 1.15; /* 1 */ margin: 0; /* 2 */ } /** * Show the overflow in IE. * 1. Show the overflow in Edge. */ button, input { /* 1 */ overflow: visible; } /** * Remove the inheritance of text transform in Edge, Firefox, and IE. * 1. Remove the inheritance of text transform in Firefox. */ button, select { /* 1 */ text-transform: none; } /** * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` * controls in Android 4. * 2. Correct the inability to style clickable types in iOS and Safari. */ button, html [type="button"], [type="reset"], [type="submit"] { -webkit-appearance: button; /* 2 */ } /** * Remove the inner border and padding in Firefox. */ button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { border-style: none; padding: 0; } /** * Restore the focus styles unset by the previous rule. */ button:-moz-focusring, [type="button"]:-moz-focusring, [type="reset"]:-moz-focusring, [type="submit"]:-moz-focusring { outline: 1px dotted ButtonText; } /** * Correct the padding in Firefox. */ fieldset { padding: 0.35em 0.75em 0.625em; } /** * 1. Correct the text wrapping in Edge and IE. * 2. Correct the color inheritance from `fieldset` elements in IE. * 3. Remove the padding so developers are not caught out when they zero out * `fieldset` elements in all browsers. */ legend { box-sizing: border-box; /* 1 */ color: inherit; /* 2 */ display: table; /* 1 */ max-width: 100%; /* 1 */ padding: 0; /* 3 */ white-space: normal; /* 1 */ } /** * 1. Add the correct display in IE 9-. * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera. */ progress { display: inline-block; /* 1 */ vertical-align: baseline; /* 2 */ } /** * Remove the default vertical scrollbar in IE. */ textarea { overflow: auto; } /** * 1. Add the correct box sizing in IE 10-. * 2. Remove the padding in IE 10-. */ [type="checkbox"], [type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ } /** * Correct the cursor style of increment and decrement buttons in Chrome. */ [type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { height: auto; } /** * 1. Correct the odd appearance in Chrome and Safari. * 2. Correct the outline style in Safari. */ [type="search"] { -webkit-appearance: textfield; /* 1 */ outline-offset: -2px; /* 2 */ } /** * Remove the inner padding and cancel buttons in Chrome and Safari on macOS. */ [type="search"]::-webkit-search-cancel-button, [type="search"]::-webkit-search-decoration { -webkit-appearance: none; } /** * 1. Correct the inability to style clickable types in iOS and Safari. * 2. Change font properties to `inherit` in Safari. */ ::-webkit-file-upload-button { -webkit-appearance: button; /* 1 */ font: inherit; /* 2 */ } /* Interactive ========================================================================== */ /* * Add the correct display in IE 9-. * 1. Add the correct display in Edge, IE, and Firefox. */ details, menu { display: block; } /* * Add the correct display in all browsers. */ summary { display: list-item; } /* Scripting ========================================================================== */ /** * Add the correct display in IE 9-. */ canvas { display: inline-block; } /** * Add the correct display in IE. */ template { display: none; } /* Hidden ========================================================================== */ /** * Add the correct display in IE 10-. */ [hidden] { display: none; } @font-face { font-family: "Helvetica Neue For Number"; src: local("Helvetica Neue"); unicode-range: U+30-39; } * { box-sizing: border-box; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } *:before, *:after { box-sizing: border-box; } html, body { width: 100%; height: 100%; } body { font-family: "Helvetica Neue For Number", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 12px; line-height: 1.5; color: rgba(0, 0, 0, 0.65); background-color: #fff; } body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, textarea, p, blockquote, th, td, hr, button, article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { margin: 0; padding: 0; } button, input, select, textarea { font-family: inherit; font-size: inherit; line-height: inherit; color: inherit; } ul, ol { list-style: none; } input::-ms-clear, input::-ms-reveal { display: none; } ::-moz-selection { background: #108ee9; color: #fff; } ::selection { background: #108ee9; color: #fff; } h1, h2, h3, h4, h5, h6 { color: rgba(0, 0, 0, 0.85); font-weight: 500; } a { color: #108ee9; background: transparent; text-decoration: none; outline: none; cursor: pointer; -webkit-transition: color .3s ease; transition: color .3s ease; } a:focus { text-decoration: underline; -webkit-text-decoration-skip: ink; text-decoration-skip: ink; } a:hover { color: #49a9ee; } a:active { color: #0e77ca; } a:active, a:hover { outline: 0; text-decoration: none; } a[disabled] { color: rgba(0, 0, 0, 0.25); cursor: not-allowed; pointer-events: none; }
其實,有些時候,使用 ant.design 沒有辦法滿足我們的樣式要求,所以,我們就需要使用 !important 來先找到樣式然后強制來覆蓋,但這絕對不是最佳實踐。
下面我們介紹一種比較好用的方法。
第三部分: 使用(引入CSS較好的做法)、解析
之前我們引入css的方式是直接把整個css文件引入,這時一種不好的做法,因為在一個項目中也許我們僅僅是使用其中的幾個組件,所以引入所有的css是完全沒有必要的。
那么解決辦法是什么呢?
拿 message 舉例,我們可以在node_modules下的antd下的message中看到如下結構:
即,這里不僅僅有 index.js 和 index.d.ts 兩者構成的js組件,還有一個 style 文件夾,這個文件夾中描述了對組件的樣式。我們是可以直接從這里引入的。
比如,我們需要引入 message 的組件和相關的css,可以像下面這樣:
import { message } from 'antd'; require('antd/lib/message/style')
當然也可以不用require, 用 import 也是可以的,如下所示:
import { message } from 'antd'; import 'antd/lib/message/style'
對於第一條語句,很容易理解,即引入了message的js組件。
對於第二條語句,由於 style 是一個文件夾,根據規則,是默認尋找其中的 index.js ,我們看看 index.js 中的內容是什么?
'use strict'; require('../../style/index.less'); require('./index.less');
其中的 ../../style/index.less 是ant.design的主題配置,比如,我們可以配置它的整體的顏色、文字大小等等。
另外,就是引入了這個style下面的 index.less, 比如message下的less是這樣的:
@import "../../style/themes/default"; @message-prefix-cls: ~"@{ant-prefix}-message"; .@{message-prefix-cls} { font-size: 16px; position: fixed; z-index: @zindex-message; width: 100%; top: 0px; left: 0; pointer-events: none; &-notice { padding: 16px; padding-top: 16px; text-align: center; &:first-child { margin-top: -8px; } } &-notice-content { padding: 16px 32px; border-radius: @border-radius-base; box-shadow: @shadow-2; background: @component-background; display: inline-block; pointer-events: all; } &-success .@{iconfont-css-prefix} { color: @success-color; } &-error .@{iconfont-css-prefix} { color: @error-color; } &-warning .@{iconfont-css-prefix} { color: @warning-color; } &-info .@{iconfont-css-prefix}, &-loading .@{iconfont-css-prefix} { color: @info-color; } .@{iconfont-css-prefix} { margin-right: 8px; font-size: @font-size-lg; top: 1px; position: relative; } &-notice.move-up-leave.move-up-leave-active { animation-name: MessageMoveOut; overflow: hidden; animation-duration: 0.3s; } } @keyframes MessageMoveOut { 0% { opacity: 1; max-height: 150px; padding: 8px; } 100% { opacity: 0; max-height: 0; padding: 0; } }
我們如果覺得樣式不合適,只需要在這個less文件中直接修改就可以了。這樣就會經過編譯在頁面上顯示出效果。
那么其中的js文件又代表什么呢? 即一個是 index.js, 另外一個是 index.d.js,這兩個文件就描述了這個 message 組件。 我們首先來看看 index.js 內容吧,直接在代碼中注釋解釋:'use strict';// 這句聲明表示這個文件是一個可以被引入的模塊。
Object.defineProperty(exports, "__esModule", { value: true });
// 引入react var _react = require('react'); var _react2 = _interopRequireDefault(_react);
// 引入 rcNotification var _rcNotification = require('rc-notification'); var _rcNotification2 = _interopRequireDefault(_rcNotification);
// 引入 icon 組件,即通知正確、錯誤時的圖標icon var _icon = require('../icon'); var _icon2 = _interopRequireDefault(_icon); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
// 通知的toast默認時間設置為3s var defaultDuration = 3;
// 這里的void后面可以是一個表達式,但是這個表達式的返回結果永遠是undefined。 var defaultTop = void 0; var messageInstance = void 0; var key = 1;
// 這里應該是組件的前綴 var prefixCls = 'ant-message'; var getContainer = void 0;
// 獲取一個 message 實例 function getMessageInstance() { messageInstance = messageInstance || _rcNotification2['default'].newInstance({ prefixCls: prefixCls, transitionName: 'move-up', style: { top: defaultTop }, getContainer: getContainer }); return messageInstance; }
function notice(content) { var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultDuration; var type = arguments[2]; var onClose = arguments[3];
// 定義icon的樣式 var iconType = { info: 'info-circle', success: 'check-circle', error: 'cross-circle', warning: 'exclamation-circle', loading: 'loading' }[type];
// 在notice(通知)的時候創建一個實例
var instance = getMessageInstance(); instance.notice({ key: key, duration: duration, style: {}, content: _react2['default'].createElement( 'div', { className: prefixCls + '-custom-content ' + prefixCls + '-' + type }, _react2['default'].createElement(_icon2['default'], { type: iconType }), _react2['default'].createElement( 'span', null, content ) ), onClose: onClose }); return function () { var target = key++; return function () { instance.removeNotice(target); }; }(); }
// 關鍵: 暴露出去的方法,就是我們在組件中引入message時可以直接調用的方法。 exports['default'] = { info: function info(content, duration, onClose) { return notice(content, duration, 'info', onClose); }, success: function success(content, duration, onClose) { return notice(content, duration, 'success', onClose); }, error: function error(content, duration, onClose) { return notice(content, duration, 'error', onClose); }, // Departed usage, please use warning() warn: function warn(content, duration, onClose) { return notice(content, duration, 'warning', onClose); }, warning: function warning(content, duration, onClose) { return notice(content, duration, 'warning', onClose); }, loading: function loading(content, duration, onClose) { return notice(content, duration, 'loading', onClose); }, config: function config(options) { if (options.top !== undefined) { defaultTop = options.top; messageInstance = null; // delete messageInstance for new defaultTop } if (options.duration !== undefined) { = options.duration; } if (options.prefixCls !== undefined) { prefixCls = options.prefixCls; } if (options.getContainer !== undefined) { getContainer = options.getContainer; } }, destroy: function destroy() { if (messageInstance) { messageInstance.destroy(); messageInstance = null; } } }; module.exports = exports['default'];
可以看到,這些方法,如 message.info() 、message.warning()都可以接收三個參數
- 希望通知的信息
- 這個通知信息所持續的時間
- 當通知結束之后的回調函數
ok!下面我們來看看 index.d.ts 文件:
/// <reference types="react" /> import React from 'react'; export declare type ConfigOnClose = () => void; export interface ConfigOptions { top?: number; duration?: number; prefixCls?: string; getContainer?: () => HTMLElement; } declare const _default: { info(content: React.ReactNode, duration?: number | undefined, onClose?: ConfigOnClose | undefined): () => void; success(content: React.ReactNode, duration?: number | undefined, onClose?: ConfigOnClose | undefined): () => void; error(content: React.ReactNode, duration?: number | undefined, onClose?: ConfigOnClose | undefined): () => void; warn(content: React.ReactNode, duration?: number | undefined, onClose?: ConfigOnClose | undefined): () => void; warning(content: React.ReactNode, duration?: number | undefined, onClose?: ConfigOnClose | undefined): () => void; loading(content: React.ReactNode, duration?: number | undefined, onClose?: ConfigOnClose | undefined): () => void; config(options: ConfigOptions): void; destroy(): void; }; export default _default;
哈哈 ,看不懂,等看完了ts回來講解。
第四部分: ant.design的柵格系統
在 ant.design 中,對於柵格系統的設計和bootstrap中的設計是極其類似的,核心概念為: Row一定是最外層的, Col一定是分布在Row中的, 內容一定是在Col里的, 當然,在Col中我們還可以嵌套Row,在antd中, Col被分成了24分(與bootstrap的12份是類似的)。
在Col中,我們可以使用span={number}來制定一個Col的寬度,具體的做法是使用 百分比 來划分, 如 span={4} 的占滿,那么每一份就是 16.6667% , 如果 span={12} 占滿,那么每一份就是 50%。。。。 依次類推。
另外,在Col中我們還可以使用offset來進行便宜,正值為向右偏移,使用的原理是 margin-left 或者是 margin-right。
我們還可以在Row中設置 gutter={number } 這個值就是柵格的間距,具體實現原理就是對div根據百分比來划分,然后在div內容使用padding,這時content肯定是減小的。
除此之外,還可以在 Col 中設置 push={number} 以及 pull={number},實現原理也非常簡單,就是使用元素的 position: relative;值,通過 left=百分比;以及right=百分比; 這樣就可以實現pull 和 push 就可以了。
當然,我們還可以使用 Row 的flex進行布局,這種布局方式只需要在 Row 上設置 type="flex",就可以設置豎直和水平對齊方式了。
豎直對齊方式:
- align="top" 向上對齊
- align="middle" 中間對齊
- alegn="bottom" 向下對齊
水平對其方式:
- justify="start" 左對齊
- justify='end' 右對齊
- justify="center" 中間對齊
- justify='space-between' 中間
- jusify="space-around" 中間
這些flex布局的原理也很簡單,就是直接使用css3的flex, 如align-items以及 justify-content。
另外, ant.design也是支持響應式布局的 。 和bootstrap一樣。
注意點:
- 一般在我們制作表格的時候,可以使用 ant.design 的柵格系統,比如,左邊是說明性文字,右邊是選擇項或者是input框。 整體使用flex布局即可。 左邊的給一個固定的寬度,如span={4},右邊的就是span={24}了, 並且在右邊,如果是input框就比較好解決,如果是幾個框,我們需要分開排列,就需要使用一個 <Row>,然后設置flex,其中justify應該是space-between,而能是start、end、center或者是 space-around。 因為對於 start、end、center,會使得幾個框都會貼的很緊(除非是我們在其中再添加一個div,然后添加一個padding,這樣才能做到分割),那么space-between和space-around的區別是什么?前者是兩邊貼近然后中間有空位置,而后者是兩邊的距離為中間padding的一般。
- 另外,我們也是可以用gutter的,但是最好不用,因為,gutter在兩邊也會有間距,這樣對於對齊的控制非常麻煩。