成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

antd源碼解讀(3)- Button

miguel.jiang / 3670人閱讀

Button

Button包括了兩個(gè)組件,ButtonButtonGroup。

ButtonProps

看一個(gè)組件首先看的是他的傳參也就是props,所以我們這里先看Button組件的ButtonProps

  export type ButtonType = "primary" | "ghost" | "dashed" | "danger";
  export type ButtonShape = "circle" | "circle-outline";
  export type ButtonSize = "small" | "large";

  // typescript語(yǔ)法,這里表示的是一些參數(shù),參數(shù)后面跟上 ? 是可選參數(shù)的意思,不跟就是必須參數(shù)
  // 參數(shù)后面所跟的就是參數(shù)的類型,類型可以是自定義的類型,就如‘ButtonType’,‘ButtonShape’,‘ButtonSize’
  // 也可以是函數(shù)或者類,如React.FormEventHandler 
  // 詳情請(qǐng)看這里 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;
  }
Render()

看完其參數(shù)有哪些之后我們就直接跳過(guò)組件內(nèi)部的其他的東西,直接看他的渲染函數(shù),畢竟這里是執(zhí)行的入口
這里順帶提一下這句代碼

// 這里的意思是將傳入兩個(gè)參數(shù),React.Component的參數(shù)第一個(gè)是Props,第二個(gè)是state,
// 然后利用typescript的類型檢查,Props類型需要時(shí)上面定義的ButtonProps中的可選參數(shù)中的變量名
// state這里傳入任意都行
export default class Button extends React.Component
// 接下來(lái)是render()
  render() {
    // 將參數(shù)從props解構(gòu)出來(lái)
    const {
      type, shape, size = "", className, htmlType, children, icon, prefixCls, ghost, ...others,
    } = this.props;
    // 將loading和clicked兩個(gè)狀態(tài)從state解構(gòu)
    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,不過(guò)官方給的是如果需要用到icon的話最好自己寫在里面

    const iconNode = iconType ?  : null; 

    const needInserted = React.Children.count(children) === 1 && (!iconType || iconType === "loading");

    // 重點(diǎn)在這里,敲黑板了
    // 這里引用了React.Children.map這個(gè)函數(shù)來(lái)對(duì)這個(gè)包裹在這個(gè)Button組件中的內(nèi)容渲染出來(lái)
    // 其中insertSpace()這個(gè)函數(shù)也有意思,這個(gè)函數(shù)主要是為了在當(dāng)組建中間寫的是中文漢字的時(shí)
    // 候給其漢字之間添加一個(gè)空格作為分隔,這里有的同學(xué)會(huì)問(wèn)為什么不用css里面的letter-space
    // 屬性,這個(gè)我也不是很清楚。。。不過(guò)他不用的話可能是是不想在英文字母中間添加空格吧

    const kids = React.Children.map(children, child => insertSpace(child, needInserted));

    return (
      
    );
  }
InsertSpace()

上面講到了這個(gè)函數(shù),這里就來(lái)仔細(xì)看看是干嘛的吧

  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.
    // 這個(gè)判斷的意思是當(dāng)這個(gè)child不是字符串也不是數(shù)字并且child.type為字符串并且child的children是漢字的情況下
    // 給其加上空格,上面說(shuō)的是代碼直譯,那么代碼意譯下來(lái)就是這樣的一個(gè)情況
    // 這種情況(所以這里他才會(huì)有一個(gè)英文注釋,說(shuō)的是不是嚴(yán)格意義的檢查,啊哈哈,尷尬的實(shí)現(xiàn)方法)
    // 
    // 這里說(shuō)明一下,child.type以及child.props.children是react在渲染的時(shí)候會(huì)給虛擬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;
  }

完整源代碼

剩下的都是一些簡(jiǎn)單的東西,也沒有什么可以講的了

  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 {
    // 這里這樣子寫只是為了方便這樣子寫B(tài)utton.Group來(lái)引用ButtonGroup這個(gè)組件,下一節(jié)將會(huì)講解這個(gè)組件
    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 });
      }
    }

    // 在組件銷毀的時(shí)候一定要記得將定時(shí)器也一同銷毀
    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 (
        
      );
    }
  }

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/89015.html

相關(guān)文章

  • antd源碼解讀(2)- Icon

    摘要:作為開發(fā)當(dāng)中使用相對(duì)頻繁的一個(gè)組件,其實(shí)現(xiàn)也很簡(jiǎn)單,但是其中比較麻煩的一部分是字體的制作,可以參看這篇文章。接口中的種屬性方法,不屬于上述六種。為事件屬性,可以大家也可以根據(jù)上面所提供的制作的方法和這樣的方式來(lái)實(shí)現(xiàn)自己的組件 Icon icon作為開發(fā)當(dāng)中使用相對(duì)頻繁的一個(gè)組件,其實(shí)現(xiàn)也很簡(jiǎn)單,但是其中比較麻煩的一部分是icon字體的制作,可以參看這篇文章。 Antd的Icon組件使用...

    fjcgreat 評(píng)論0 收藏0
  • antd源碼解讀(1)-index.js

    github: 地址gitbook: 地址 Index.js 看一個(gè)代碼的時(shí)候首先當(dāng)然是從他的入口文件開始看起,所以第一份代碼我們看的是/index.js文件 開始 打開index.js文件,代碼只有28行,其中包含了一個(gè)camelCase函數(shù)(看函數(shù)名就知道這是個(gè)給名稱進(jìn)行駝峰命名法的函數(shù)),一個(gè)req變量,以及這個(gè)的變量操作和export操作 在這個(gè)文件里面我首先查了require.conte...

    zeyu 評(píng)論0 收藏0
  • antd源碼解讀(二)Tooltip組件解析

    摘要:結(jié)構(gòu)項(xiàng)目結(jié)構(gòu)如下,負(fù)責(zé)外層封裝,負(fù)責(zé)事件綁定與渲染控制。節(jié)點(diǎn)通過(guò)決定事件綁定情況,即通過(guò)屬性綁定事件情況,事件控制組件的屬性,這里就不詳細(xì)說(shuō)了。為隱藏狀態(tài)下的添加的,并包裹懶加載組件。 引言 antd的Tooltip組件在react-componment/trigger的基礎(chǔ)上進(jìn)行封裝,而組件Popover和Popconfirm是使用Tooltip組件的進(jìn)行pop,在react-com...

    fanux 評(píng)論0 收藏0
  • React+webpack+Antd從0到1開發(fā)一個(gè)todoMvc

    摘要:在裝載組件之前調(diào)用會(huì)組件的構(gòu)造函數(shù)。當(dāng)實(shí)現(xiàn)子類的構(gòu)造函數(shù)時(shí),應(yīng)該在任何其他語(yǔ)句之前調(diào)用設(shè)置初始狀態(tài)綁定鍵盤回車事件,添加新任務(wù)修改狀態(tài)值,每次修改以后,自動(dòng)調(diào)用方法,再次渲染組件??梢酝ㄟ^(guò)直接安裝到項(xiàng)目中,使用或進(jìn)行引用。 首先我們看一下我們完成后的最終形態(tài):TodoMvc: showImg(https://segmentfault.com/img/remote/14600000085...

    sanyang 評(píng)論0 收藏0
  • antd源碼解讀(6)- Affix

    摘要:這個(gè)組件是一個(gè)圖釘組件,使用的布局,讓組件固定在窗口的某一個(gè)位置上,并且可以在到達(dá)指定位置的時(shí)候才去固定。 Affix 這個(gè)組件是一個(gè)圖釘組件,使用的fixed布局,讓組件固定在窗口的某一個(gè)位置上,并且可以在到達(dá)指定位置的時(shí)候才去固定。 AffixProps 還是老樣子,看一個(gè)組件首先我們先來(lái)看看他可以傳入什么參數(shù) // Affix export interface Affix...

    coordinate35 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<