成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專(zhuān)欄INFORMATION COLUMN

antd源碼解析(一)Form組件解析

timger / 4066人閱讀

摘要:引言看過(guò)源碼的都知道,其實(shí)是在一組組件的基礎(chǔ)上進(jìn)行了一層封裝,本文主要解讀組件的基礎(chǔ)組件,另外會(huì)略過(guò)模式下的代碼。解讀源碼首先要從自己最常用的或者感興趣的入手,首先組件最主要的還是在這個(gè)裝飾器入手。

引言

看過(guò)antd源碼的都知道,antd其實(shí)是在一組react-componment組件的基礎(chǔ)上進(jìn)行了一層ui封裝,本文主要解讀antd組件Form的基礎(chǔ)組件react-componment/form,另外會(huì)略過(guò)development模式下的warning代碼。

Form.create

解讀源碼首先要從自己最常用的或者感興趣的入手,首先f(wàn)orm組件最主要的還是在Form.create({options})這個(gè)裝飾器入手。找到項(xiàng)目下的文件createForm.js,這個(gè)文件還是主要主要對(duì)createBaseForm.js文件進(jìn)行了一層封裝,提供了一些默認(rèn)配置參數(shù),下看查看createBaseForm.js里的createBaseForm方法,改方法主要是一個(gè)裝飾器作用,包裝一個(gè)高階React組件,在props里注入一個(gè)值為formPropName(默認(rèn)為form)變量,所有功能在這個(gè)變量里完成,主要內(nèi)容如下

render() {
  const { wrappedComponentRef, ...restProps } = this.props;
  const formProps = {
    [formPropName]: this.getForm(), // 來(lái)在 formPropName默認(rèn)為form,getForm方法來(lái)自`createForm.js`
  };
  if (withRef) {
    formProps.ref = "wrappedComponent";
  } else if (wrappedComponentRef) {
    formProps.ref = wrappedComponentRef;
  }
  const props = mapProps.call(this, {
    ...formProps,
    ...restProps,
  });
  return ;
}

在裝飾器初始化的時(shí)候,F(xiàn)orm初始化了一個(gè)只屬于該組件實(shí)例的store,用來(lái)存放當(dāng)前Form組件的一些輸入的數(shù)據(jù),主要代碼如下:

const fields = mapPropsToFields && mapPropsToFields(this.props);  // mapPropsToFields來(lái)自于Form.create的配置參數(shù),用來(lái)轉(zhuǎn)化來(lái)自mobx或者redux等真正的store來(lái)源的value,以初始化該Form實(shí)例的fieldsStore
this.fieldsStore = createFieldsStore(fields || {});  // createFieldsStore來(lái)自于文件`createFieldsStore.js`文件
getFieldDecorator

柯里化函數(shù),通過(guò)id與參數(shù)聲明的輸入,返回一個(gè)函數(shù)以輸入組件為入?yún)⒌暮瘮?shù),通過(guò)該函數(shù)聲明的輸入組件與表單Form雙向數(shù)據(jù)綁定。

  ...
  getFieldDecorator(name, fieldOption) {
    const props = this.getFieldProps(name, fieldOption);  // 初始化一個(gè)field
    return (fieldElem) => {
      const fieldMeta = this.fieldsStore.getFieldMeta(name);  // 獲取變化(Form的onChange)后的field數(shù)據(jù)
      const originalProps = fieldElem.props;
      fieldMeta.originalProps = originalProps;  // 輸入組件初始化時(shí)保存的Prop
      fieldMeta.ref = fieldElem.ref;
      return React.cloneElement(fieldElem, {
        ...props,
        ...this.fieldsStore.getFieldValuePropValue(fieldMeta),  // 獲取prop屬性 value
      });
    };
  }
  ...
getFieldProps

查看函數(shù) getFieldProps,主要用來(lái)初始化輸入組件的props,將特定的函數(shù)緩存在內(nèi)部,如onChange事件,另外初次保存field到store中

  ...
  getFieldProps(name, usersFieldOption = {}) {
    if (!name) {
      throw new Error("Must call `getFieldProps` with valid name string!");
    }
    delete this.clearedFieldMetaCache[name];
    const fieldOption = {
      name,
      trigger: DEFAULT_TRIGGER,
      valuePropName: "value",
      validate: [],
      ...usersFieldOption, // 用戶(hù)輸入,如rules,initialValue
    };

    const {
      rules,
      trigger,
      validateTrigger = trigger,
      validate,
    } = fieldOption;

    const fieldMeta = this.fieldsStore.getFieldMeta(name);
    if ("initialValue" in fieldOption) {
      fieldMeta.initialValue = fieldOption.initialValue;
    }

    const inputProps = {
      ...this.fieldsStore.getFieldValuePropValue(fieldOption), // 獲取輸入組件的value,如果沒(méi)有,返回initialValue
      ref: this.getCacheBind(name, `${name}__ref`, this.saveRef),
    };
    if (fieldNameProp) { // 及value
      inputProps[fieldNameProp] = name;
    }

    const validateRules = normalizeValidateRules(validate, rules, validateTrigger); // 校驗(yàn)規(guī)則標(biāo)準(zhǔn)化
    const validateTriggers = getValidateTriggers(validateRules);
    validateTriggers.forEach((action) => {
      if (inputProps[action]) return;
      inputProps[action] = this.getCacheBind(name, action, this.onCollectValidate); // 如果設(shè)置了輸入校驗(yàn)rules,綁定onChange事件`this.onCollectValidate`
    });

    // make sure that the value will be collect
    if (trigger && validateTriggers.indexOf(trigger) === -1) {
      inputProps[trigger] = this.getCacheBind(name, trigger, this.onCollect); // 如果沒(méi)有綁定rules校驗(yàn),綁定默認(rèn)的onChange事件
    }
    const meta = {
      ...fieldMeta,
      ...fieldOption,
      validate: validateRules,
    };
    this.fieldsStore.setFieldMeta(name, meta);  // 保存field到store中
    if (fieldMetaProp) {
      inputProps[fieldMetaProp] = meta;
    }
    if (fieldDataProp) {
      inputProps[fieldDataProp] = this.fieldsStore.getField(name);
    }
    return inputProps;
  },
  ...
getCacheBind

getCacheBind方法,緩存函數(shù),使用bind方法綁定上下文并緩存部分參數(shù),返回一個(gè)新的函數(shù),用做onChange及數(shù)據(jù)校驗(yàn)。

  ...
  getCacheBind(name, action, fn) {
    if (!this.cachedBind[name]) {
      this.cachedBind[name] = {};
    }
    const cache = this.cachedBind[name];
    if (!cache[action]) {
      cache[action] = fn.bind(this, name, action); // 綁定參數(shù)并返回
    }
    return cache[action];
  },
  ...
onCollectCommon

getFieldProps方法中看到利用getCacheBind方法當(dāng)無(wú)rules的時(shí)候綁定了一個(gè)onCollect方法,onCollect方法主要調(diào)用onCollectCommon方法,并將得到的結(jié)果保存到store。

onCollectCommon(name, action, args) {
  const fieldMeta = this.fieldsStore.getFieldMeta(name);
  if (fieldMeta[action]) {  // 如果getFieldDecorator方法中的參數(shù)定義了onChange,則觸發(fā)改onChange
    fieldMeta[action](...args);
  } else if (fieldMeta.originalProps && fieldMeta.originalProps[action]) { // 如果輸入組件綁定了onChange,則觸發(fā)該onChange
    fieldMeta.originalProps[action](...args);
  }
  const value = fieldMeta.getValueFromEvent ?  // 獲取更新后的value,兼容原生組件e.target.value
    fieldMeta.getValueFromEvent(...args) :
    getValueFromEvent(...args);
  if (onValuesChange && value !== this.fieldsStore.getFieldValue(name)) {  // 如果Form.create時(shí)用戶(hù)定義有onValuesChange,則觸發(fā)
    const valuesAll = this.fieldsStore.getAllValues();
    const valuesAllSet = {};
    valuesAll[name] = value;
    Object.keys(valuesAll).forEach(key => set(valuesAllSet, key, valuesAll[key]));
    onValuesChange(this.props, set({}, name, value), valuesAllSet);
  }
  const field = this.fieldsStore.getField(name);    // 獲取合并field,并返回
  return ({ name, field: { ...field, value, touched: true }, fieldMeta });
},
onCollectValidate

在有輸入rules的時(shí)候getCacheBind方法綁定onCollectValidate作為onChange事件,該方法做了除了調(diào)用了onCollectCommon事件以外,還調(diào)用了校驗(yàn)方法validateFieldsInternal。

validateFieldsInternal

該方法主要是從store中獲取rules校驗(yàn)規(guī)則并標(biāo)準(zhǔn)化后,使用async-validator模塊進(jìn)行校驗(yàn),并把結(jié)果保存到store中,本文不做講解。

setFields

該方法主要是設(shè)置store中的field,因?yàn)閟tore的數(shù)據(jù)是不可觀測(cè)的數(shù)據(jù),不會(huì)引起頁(yè)面的重渲染,該方法也負(fù)責(zé)調(diào)用forceUpdate()強(qiáng)制更新頁(yè)面。

setFields(maybeNestedFields, callback) {
  const fields = this.fieldsStore.flattenRegisteredFields(maybeNestedFields); // 處理field嵌套問(wèn)題
  this.fieldsStore.setFields(fields);
  if (onFieldsChange) {  // 如果設(shè)置有FieldsChange事件監(jiān)聽(tīng)事件變化,則觸發(fā)事件
    const changedFields = Object.keys(fields)
      .reduce((acc, name) => set(acc, name, this.fieldsStore.getField(name)), {});
    onFieldsChange(this.props, changedFields, this.fieldsStore.getNestedAllFields());
  }
  this.forceUpdate(callback);  // 強(qiáng)制更新視圖
},
最后

主要方法大概就上面這些,其中流程差不多在每次setFields之前,會(huì)在store中存一個(gè)field的變化字段fieldMeta,在最后強(qiáng)制更新頁(yè)面的時(shí)候,將該變量取出來(lái)做處理后覆蓋到field,所有數(shù)據(jù)保存在field中,并提供了一些hock方法如setFieldsValue、validateFields等方法設(shè)置和獲取store中的field字段和值。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/94364.html

相關(guān)文章

  • 常用列表頁(yè)常見(jiàn)hook封裝解析

      我們今天來(lái)講講關(guān)于ahooks 源碼,我們目標(biāo)主要有以下幾點(diǎn):  深入了解 React hooks。  明白如何抽象自定義 hooks,且可以構(gòu)建屬于自己的 React hooks 工具庫(kù)?! ⌒〗ㄗh:培養(yǎng)閱讀學(xué)習(xí)源碼的習(xí)慣,工具庫(kù)是一個(gè)對(duì)源碼閱讀不錯(cuò)的選擇。  列表頁(yè)常見(jiàn)元素  后臺(tái)管理系統(tǒng)中常見(jiàn)典型列表頁(yè)包括篩選表單項(xiàng)、Table表格、Pagination分頁(yè)這三部分。  針對(duì)使用 Ant...

    3403771864 評(píng)論0 收藏0
  • JSON生成Form表單

    摘要:是校驗(yàn)表單組件數(shù)據(jù)正確性的字段,其值為數(shù)組,里面的數(shù)組元素可以為。所以數(shù)組元素如果為的話(huà),其內(nèi)容就是的。到目前為止,表單適合大部分的表單應(yīng)用場(chǎng)景。 JSON表單 描述 JSON表單是一個(gè)基于React的抽象組件,它可以把JSON數(shù)據(jù)格式描述的表單轉(zhuǎn)換成項(xiàng)目中的表單,它可以用簡(jiǎn)短的幾行代碼,快速的生成Form表單。JSON表單的優(yōu)點(diǎn)是: 可以快速構(gòu)建出一個(gè)表單 表單的數(shù)據(jù)、邏輯、視圖分...

    bingchen 評(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開(kāi)發(fā)個(gè)todoMvc

    摘要:在裝載組件之前調(diào)用會(huì)組件的構(gòu)造函數(shù)。當(dāng)實(shí)現(xiàn)子類(lèi)的構(gòu)造函數(shù)時(shí),應(yīng)該在任何其他語(yǔ)句之前調(diào)用設(shè)置初始狀態(tài)綁定鍵盤(pán)回車(chē)事件,添加新任務(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
  • 基于node的登入例子(node-koa-mongoose)

    摘要:前言這是一個(gè)基于實(shí)現(xiàn)的一個(gè)簡(jiǎn)單登入例子,對(duì)于剛上手想進(jìn)一步了解,前端頁(yè)面如何請(qǐng)求到服務(wù)層路由處理數(shù)據(jù)庫(kù)操作返回結(jié)果到頁(yè)面這整個(gè)過(guò)程的同學(xué)比較有用。我們來(lái)看下登入請(qǐng)求處理。操作演示演示用戶(hù)名不存在,密碼錯(cuò)誤及成功登入。 前言 這是一個(gè)基于node實(shí)現(xiàn)的一個(gè)簡(jiǎn)單登入例子,對(duì)于剛上手node想進(jìn)一步了解,前端頁(yè)面如何請(qǐng)求到服務(wù)層 -> 路由處理 -> 數(shù)據(jù)庫(kù)操作 -> 返回結(jié)果到頁(yè)面這整個(gè)過(guò)...

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

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

0條評(píng)論

閱讀需要支付1元查看
<