Button
Button包括了兩個組件,Button與ButtonGroup。
ButtonProps看一個組件首先看的是他的傳參也就是props,所以我們這里先看Button組件的ButtonProps
export type ButtonType = "primary" | "ghost" | "dashed" | "danger"; export type ButtonShape = "circle" | "circle-outline"; export type ButtonSize = "small" | "large"; // typescript語法,這里表示的是一些參數,參數后面跟上 ? 是可選參數的意思,不跟就是必須參數 // 參數后面所跟的就是參數的類型,類型可以是自定義的類型,就如‘ButtonType’,‘ButtonShape’,‘ButtonSize’ // 也可以是函數或者類,如React.FormEventHandlerRender()// 詳情請看這里 https://www.tslang.cn/docs/handbook/interfaces.html export interface ButtonProps { type?: ButtonType; htmlType?: string; icon?: string; shape?: ButtonShape; size?: ButtonSize; onClick?: React.FormEventHandler ; onMouseUp?: React.FormEventHandler ; onMouseDown?: React.FormEventHandler ; loading?: boolean | { delay?: number }; disabled?: boolean; style?: React.CSSProperties; prefixCls?: string; className?: string; ghost?: boolean; }
看完其參數有哪些之后我們就直接跳過組件內部的其他的東西,直接看他的渲染函數,畢竟這里是執行的入口
這里順帶提一下這句代碼
// 這里的意思是將傳入兩個參數,React.Component的參數第一個是Props,第二個是state, // 然后利用typescript的類型檢查,Props類型需要時上面定義的ButtonProps中的可選參數中的變量名 // state這里傳入任意都行 export default class Button extends React.Component
// 接下來是render() render() { // 將參數從props解構出來 const { type, shape, size = "", className, htmlType, children, icon, prefixCls, ghost, ...others, } = this.props; // 將loading和clicked兩個狀態從state解構 const { loading, clicked } = this.state; // large => lg // small => sm let sizeCls = ""; switch (size) { case "large": sizeCls = "lg"; break; case "small": sizeCls = "sm"; default: break; } // 組建樣式 const classes = classNames(prefixCls, className, { [`${prefixCls}-${type}`]: type, [`${prefixCls}-${shape}`]: shape, [`${prefixCls}-${sizeCls}`]: sizeCls, [`${prefixCls}-icon-only`]: !children && icon, [`${prefixCls}-loading`]: loading, [`${prefixCls}-clicked`]: clicked, [`${prefixCls}-background-ghost`]: ghost, }); // 是否需要加載 const iconType = loading ? "loading" : icon; // 是否需要添加Icon,不過官方給的是如果需要用到icon的話最好自己寫在里面 const iconNode = iconType ?InsertSpace(): null; const needInserted = React.Children.count(children) === 1 && (!iconType || iconType === "loading"); // 重點在這里,敲黑板了 // 這里引用了React.Children.map這個函數來對這個包裹在這個Button組件中的內容渲染出來 // 其中insertSpace()這個函數也有意思,這個函數主要是為了在當組建中間寫的是中文漢字的時 // 候給其漢字之間添加一個空格作為分隔,這里有的同學會問為什么不用css里面的letter-space // 屬性,這個我也不是很清楚。。。不過他不用的話可能是是不想在英文字母中間添加空格吧 const kids = React.Children.map(children, child => insertSpace(child, needInserted)); return ( ); }
上面講到了這個函數,這里就來仔細看看是干嘛的吧
const rxTwoCNChar = /^[u4e00-u9fa5]{2}$/;
// 這里的bind有必要好好的理解一下
const isTwoCNChar = rxTwoCNChar.test.bind(rxTwoCNChar);
function isString(str: any) {
return typeof str === "string";
}
// Insert one space between two chinese characters automatically.
function insertSpace(child: React.ReactChild, needInserted: boolean) {
// Check the child if is undefined or null.
if (child == null) {
return;
}
const SPACE = needInserted ? " " : "";
// strictNullChecks oops.
// 這個判斷的意思是當這個child不是字符串也不是數字并且child.type為字符串并且child的children是漢字的情況下
// 給其加上空格,上面說的是代碼直譯,那么代碼意譯下來就是這樣的一個情況
// 這種情況(所以這里他才會有一個英文注釋,說的是不是嚴格意義的檢查,啊哈哈,尷尬的實現方法)
//
// 這里說明一下,child.type以及child.props.children是react在渲染的時候會給虛擬dom添加的一些屬性,如圖
if (typeof child !== "string" && typeof child !== "number" &&
isString(child.type) && isTwoCNChar(child.props.children)) {
return React.cloneElement(child, {},
child.props.children.split("").join(SPACE));
}
// 這種情況就很明了了 就是Button組件中寫的漢字
if (typeof child === "string") {
if (isTwoCNChar(child)) {
child = child.split("").join(SPACE);
}
return {child};
}
return child;
}
完整源代碼
剩下的都是一些簡單的東西,也沒有什么可以講的了
import React from "react"; import PropTypes from "prop-types"; import classNames from "classnames"; import omit from "omit.js"; import Icon from "../icon"; import Group from "./button-group"; const rxTwoCNChar = /^[u4e00-u9fa5]{2}$/; const isTwoCNChar = rxTwoCNChar.test.bind(rxTwoCNChar); function isString(str: any) { return typeof str === "string"; } // Insert one space between two chinese characters automatically. function insertSpace(child: React.ReactChild, needInserted: boolean) { // Check the child if is undefined or null. if (child == null) { return; } const SPACE = needInserted ? " " : ""; // strictNullChecks oops. if (typeof child !== "string" && typeof child !== "number" && isString(child.type) && isTwoCNChar(child.props.children)) { return React.cloneElement(child, {}, child.props.children.split("").join(SPACE)); } if (typeof child === "string") { if (isTwoCNChar(child)) { child = child.split("").join(SPACE); } return {child}; } return child; } export type ButtonType = "primary" | "ghost" | "dashed" | "danger"; export type ButtonShape = "circle" | "circle-outline"; export type ButtonSize = "small" | "large"; export interface ButtonProps { type?: ButtonType; htmlType?: string; icon?: string; shape?: ButtonShape; size?: ButtonSize; onClick?: React.FormEventHandler; onMouseUp?: React.FormEventHandler ; onMouseDown?: React.FormEventHandler ; loading?: boolean | { delay?: number }; disabled?: boolean; style?: React.CSSProperties; prefixCls?: string; className?: string; ghost?: boolean; } export default class Button extends React.Component { // 這里這樣子寫只是為了方便這樣子寫Button.Group來引用ButtonGroup這個組件,下一節將會講解這個組件 static Group: typeof Group; static __ANT_BUTTON = true; static defaultProps = { prefixCls: "ant-btn", loading: false, clicked: false, ghost: false, }; static propTypes = { type: PropTypes.string, shape: PropTypes.oneOf(["circle", "circle-outline"]), size: PropTypes.oneOf(["large", "default", "small"]), htmlType: PropTypes.oneOf(["submit", "button", "reset"]), onClick: PropTypes.func, loading: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]), className: PropTypes.string, icon: PropTypes.string, }; timeout: number; delayTimeout: number; constructor(props: ButtonProps) { super(props); this.state = { loading: props.loading, }; } componentWillReceiveProps(nextProps: ButtonProps) { const currentLoading = this.props.loading; const loading = nextProps.loading; if (currentLoading) { clearTimeout(this.delayTimeout); } if (typeof loading !== "boolean" && loading && loading.delay) { this.delayTimeout = setTimeout(() => this.setState({ loading }), loading.delay); } else { this.setState({ loading }); } } // 在組件銷毀的時候一定要記得將定時器也一同銷毀 componentWillUnmount() { if (this.timeout) { clearTimeout(this.timeout); } if (this.delayTimeout) { clearTimeout(this.delayTimeout); } } handleClick = (e: React.MouseEvent ) => { // Add click effect this.setState({ clicked: true }); clearTimeout(this.timeout); this.timeout = setTimeout(() => this.setState({ clicked: false }), 500); const onClick = this.props.onClick; if (onClick) { onClick(e); } } render() { const { type, shape, size = "", className, htmlType, children, icon, prefixCls, ghost, ...others, } = this.props; const { loading, clicked } = this.state; // large => lg // small => sm let sizeCls = ""; switch (size) { case "large": sizeCls = "lg"; break; case "small": sizeCls = "sm"; default: break; } const classes = classNames(prefixCls, className, { [`${prefixCls}-${type}`]: type, [`${prefixCls}-${shape}`]: shape, [`${prefixCls}-${sizeCls}`]: sizeCls, [`${prefixCls}-icon-only`]: !children && icon, [`${prefixCls}-loading`]: loading, [`${prefixCls}-clicked`]: clicked, [`${prefixCls}-background-ghost`]: ghost, }); const iconType = loading ? "loading" : icon; const iconNode = iconType ? : null; const needInserted = React.Children.count(children) === 1 && (!iconType || iconType === "loading"); const kids = React.Children.map(children, child => insertSpace(child, needInserted)); return ( ); } }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/89015.html
摘要:作為開發當中使用相對頻繁的一個組件,其實現也很簡單,但是其中比較麻煩的一部分是字體的制作,可以參看這篇文章。接口中的種屬性方法,不屬于上述六種。為事件屬性,可以大家也可以根據上面所提供的制作的方法和這樣的方式來實現自己的組件 Icon icon作為開發當中使用相對頻繁的一個組件,其實現也很簡單,但是其中比較麻煩的一部分是icon字體的制作,可以參看這篇文章。 Antd的Icon組件使用...
github: 地址gitbook: 地址 Index.js 看一個代碼的時候首先當然是從他的入口文件開始看起,所以第一份代碼我們看的是/index.js文件 開始 打開index.js文件,代碼只有28行,其中包含了一個camelCase函數(看函數名就知道這是個給名稱進行駝峰命名法的函數),一個req變量,以及這個的變量操作和export操作 在這個文件里面我首先查了require.conte...
摘要:結構項目結構如下,負責外層封裝,負責事件綁定與渲染控制。節點通過決定事件綁定情況,即通過屬性綁定事件情況,事件控制組件的屬性,這里就不詳細說了。為隱藏狀態下的添加的,并包裹懶加載組件。 引言 antd的Tooltip組件在react-componment/trigger的基礎上進行封裝,而組件Popover和Popconfirm是使用Tooltip組件的進行pop,在react-com...
摘要:在裝載組件之前調用會組件的構造函數。當實現子類的構造函數時,應該在任何其他語句之前調用設置初始狀態綁定鍵盤回車事件,添加新任務修改狀態值,每次修改以后,自動調用方法,再次渲染組件。可以通過直接安裝到項目中,使用或進行引用。 首先我們看一下我們完成后的最終形態:TodoMvc: showImg(https://segmentfault.com/img/remote/14600000085...
摘要:這個組件是一個圖釘組件,使用的布局,讓組件固定在窗口的某一個位置上,并且可以在到達指定位置的時候才去固定。 Affix 這個組件是一個圖釘組件,使用的fixed布局,讓組件固定在窗口的某一個位置上,并且可以在到達指定位置的時候才去固定。 AffixProps 還是老樣子,看一個組件首先我們先來看看他可以傳入什么參數 // Affix export interface Affix...
閱讀 362·2024-11-06 13:38
閱讀 738·2024-09-10 13:19
閱讀 866·2024-08-22 19:45
閱讀 1363·2021-11-19 09:40
閱讀 2598·2021-11-18 13:14
閱讀 4266·2021-10-09 10:02
閱讀 2283·2021-08-21 14:12
閱讀 1268·2019-08-30 15:54