Rc-Form源碼分析
作者:姚觀壽,高級前端工程師,天虹數字靈智科技
Rc-Form功能: 主要是用來 創建和收集字段的數據和校驗字段錯誤信息,讓開發程序員少代碼能實現這個的功能。
-
接下來我們來一起看看Rc-Form整個代碼構思,Rc-Form 主要分為幾個模塊 createBaseForm 的 getForm 向整個組件props注入 setFieldsValue, getFieldsValue,resetFields,validateFields ,getFieldDecorator, getFieldProps。
-
createFieldsStore 是用來存儲字段fields value 和 error 和 方法。里面用到了 訂閱和發布模式。類似於redux的一個東西,主要核心方法:setFields,resetFields,getFieldValuePropValue, clearField,getFieldsError。
代碼和程序流程圖思維導圖
- 如果你覺得不錯,請幫我在git倉庫上點贊,謝謝了,你的支持是我開源的動力。
- git逐行分析源碼地址 : https://github.com/qq281113270/antd-rcfom.git
-
Rc-Form 源碼基本構思: http://naotu.baidu.com/file/5548c203caa4d01bccc80660deec923d?token=42d2b5b01a256c28
Rc-Form 源碼詳細分析:http://naotu.baidu.com/file/bb9abeca5d9a6878c6a27202dd9378dd?token=9768523373fe9934
-
Rc-Form文件分析
接下來我們細說整個代碼。
首先我們需要把這個code下載下來。第一步安裝node_modules
npm i --save rc-form
這樣就可以把rc-form源碼下載下來了,
然后我們最好啟動一個react項目,當然我們可以使用react-create-app創建一個react項目。
然后把rc-form源碼包源碼最好拷貝到react項目中的src 目錄中,這樣后期我們在rc-form組件中寫上注釋,還可以保留。
下載下來之后_rc-form@2.4.11@rc-form 包會有幾個文件夾目錄。一般webpack 默認引用的的是es包。
outputpath
├── dist # umd module
UMD(Universal Module Definition)是 AMD 和 CommonJS 的糅合,跨平台的解決方案
UMD 打包出來的文件可以直接通過 script 插件 html 中使用
;(function(root, factory) {
if (typeof exports === 'object' && typeof module === 'object')
module.exports = factory()
else if (typeof define === 'function' && define.amd) define([], factory)
else if (typeof exports === 'object') exports['A'] = factory()
else root['A'] = factory()
})(window, function() {
//...
})
├── es # es module
ES Module 不是對象,是使用 export 顯示指定輸出,再通過 import 輸入。此法為編譯時加載,編譯時遇到 import 就會生成一個只讀引用。等到運行時就會根據此引用去被加載的模塊取值。所以不會加載模塊所有方法,僅取所需。
export const m = 1
export {
m
}
├── lib # commonjs module
CommonJS 模塊是對象,是運行時加載,運行時才把模塊掛載在 exports 之上(加載整個模塊的所有),加載模塊其實就是查找對象屬性。
導出使用 module.exports,也可以 exports。就是在此對象上掛屬性。exports 指向 module.exports,即 exports= module.exports
加載模塊通過 require 關鍵字引用
module.exports.add = function add() {
return
}
exports.sub = function sub() {
return
}
const a = require('a.js')
如果你喜歡 當然 也可以直接看 cdn 包。
-
接下來我們來看文件
createBaseForm.js
這個js主要用於創造基本的 form 組件
他的實現主要利用了react 的 hoc 高級組件方式實現,原理其實就是返回一個匿名函數然后在函數中傳遞一個子組件進來,然后利用 hoc 高階組件 把props的form 注入進來給children組件,實現例子,這里用到以前的一些知識點 比如閉包,函數式編程,函數式柯里化。所以下面我們來簡單的實現一個props.form 注入 子組件中
// 因為第一層需要傳遞參數
const createForm = (options) => {
return (Component) => {
return class Form extends React.Component {
getForm() {
return {
getFieldsValue: () => {}, // 獲取字段值得函數
getFieldValue: () => {}, // 獲取單個值得函數
getFieldInstance: () => {}, // 獲取字段實例
setFieldsValue: () => {}, // 設置字段值
setFields: () => {}, // 設置字段 新的值
setFieldsInitialValue: () => {}, // 設置初始化值的函數
getFieldDecorator: () => {}, // 用於和表單進行雙向綁定,詳見下方描述 裝飾組件,促進雙向綁定的修飾器
getFieldProps: () => {}, // 創建待驗證的表單 設置字段元數據,返回 計算被修飾組件的屬性
getFieldsError: () => {}, //獲取一組輸入控件的 Error ,如不傳入參數,則獲取全部組件的 Error
getFieldError: () => {}, //獲取某個輸入控件的 Error
isFieldValidating: () => {}, //判斷一個輸入控件是否在校驗狀態
isFieldsValidating: () => {}, // 判斷字段是否在校驗中
isFieldsTouched: () => {}, //判斷是否任一輸入控件經歷過 getFieldDecorator 的值收集時機 options.trigger
isFieldTouched: () => {}, //判斷一個輸入控件是否經歷過 getFieldDecorator 的值收集時機 options.trigger
isSubmitting: () => {}, // 是否在 提交狀態
submit: () => {}, // 表單提交函數
validateFields: () => {}, //驗證字段,返回promise
resetFields: () => {}, // 重置字段
};
}
render() {
const props = {
form: this.getForm.call(this),
};
return <Component {...props} />;
}
};
};
};
class BaseForm extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
console.log(this.props);
debugger;
}
render() {
return (
<form>
<input />
<select>
<option>1</option>
</select>
</form>
);
}
}
const Form = createForm({ name: "abc" })(BaseForm);
ReactDOM.render(<Form />, document.getElementById("example"));連接createFieldsStore類的各種方法
-
props的form上的方法大多數是調用createFieldsStore類的方法,通過調用createFieldsStore 的各種方法實現控制字段的增刪改查。
createFieldsStore.js
-
createFieldsStore 可以理解是用於存儲字段信息值,包括字段值和校驗,錯誤信息 還有 事件等。可以理解成倉庫比如像redux這種。然后這個類會有各種方法包括增刪改查字段,校驗字段等。
-
數據格式:
-
每創建一個form 表單( 比如 createForm()(RcForm) ) 就會實例化createFieldsStore 一次,同時該createFieldsStore 就會產生一個實例屬性fields和一個實例屬性fieldsMeta
-
fields 是validateFields 調用回調函數之后,傳遞給用戶的field值,用來記錄用戶輸入值的對象。 數據格式為字段名稱作為key, 里面 是對象value值 :
{
fieldName:{
value: "1"
}
}
-
-
-
fieldsMeta數據 ,該數據作用是為RcForm存儲操作記錄使用的, 數據格式為字段名稱作為key代表的是哪個字段的,然后后面是對象,對象里面存放着字段的事件,校驗,初始化值,屬性等
-
-
-
-
-
getFieldMeta // 獲取單個字段的getFieldMeta 對象,如果沒有則為 新增 一個空對象
-
setFieldMeta // 設置 fieldsMeta 字段信息
-
clearField // 清除Field和Meta字段
-
-
fields的設置和刪除字段和獲取值方法,
-
setFields // 設置字段 新的值
-
clearField // 清除Field和Meta字段
-
resetFields // 重置value
-
getValueFromFields // 獲取字段的value值
-
getFieldValuePropValue // 獲取字段的value 值
-
getFieldsValue // 獲取字段的值
-
getAllValues // 獲取全部字段的值
-
getAllFieldsName //獲取全部字段名稱
-
getFieldsError // 獲取字段錯誤信息
-
-
createFormField.js
-
該類是為每一個字段創建一個對象用來存儲該字段的數據
-
其實該類初始化並沒有做什么,可以用一個單列模式去寫就可以了。
創建Form程序流程
-
一開始會調用 createBaseForm,進行 初始化 form表單一些參數比如
createBaseForm(options)(Component)
//options 為整個表單配置的參數
// Component 表單組件 為改組件注入props.form
createBaseForm 組件的 getInitialState
創建 初始化 fieldsStore
getFieldDecorator
-
// 用於和表單進行雙向綁定,詳見下方描述 裝飾組件,促進雙向綁定的修飾器
-
實際上他主要也是調用getFieldProps 方法,
-
通過閉包,hoc高階組建,利用React.cloneElement 隱形 把 props 的value和onChange注入 到組建中
-
以下片段代碼
// 用於和表單進行雙向綁定,詳見下方描述 裝飾組件,促進雙向綁定的修飾器
getFieldDecorator: function getFieldDecorator(
name, // 字段名稱
fieldOption // 字段設置參數
) {
var _this2 = this;
// 創建待驗證的表單 設置字段元數據,返回 計算被修飾組件的屬性
var props = this.getFieldProps(name, fieldOption);
return function (
fieldElem // 組件 也可以理解為react 的 vnode 虛擬dom
) {
// .....
return React.cloneElement(
fieldElem, //原來的vnode
// props 屬性
_extends(
{},
props, // 用戶傳進來的 props 屬性
// 獲取value 屬性值
_this2.fieldsStore.getFieldValuePropValue(fieldMeta)
)
);
.....
getFieldProps
-
該方法主要是返回 onChange 方法和 value 讓組件變成受控組件,促進雙向綁定的修飾器。
-
調用trigger (onCollectValidate)和validateTriggers方法(onCollect)
-
為Meta 類添加一個 MetaFiel 對象
-
// 獲取單個字段的getFieldMeta 對象 這個是字段 信息 和設置 Meta 初始化值作用
//
var fieldMeta = this.fieldsStore.getFieldMeta(name);
//獲取字段選項參數
var fieldOption = _extends(
{
name: name, // 字段名稱
trigger: DEFAULT_TRIGGER, //onChange 收集子節點的值的時機
valuePropName: "value", // 字段value
validate: [], // 驗證 空數組
},
usersFieldOption // 字段選項參數
);
/// ... 省略代碼
return inputProps;
normalizeValidateRules 獲取字段驗證規則
/*
獲取收集字段驗證規則,並添加到隊列中
*/
function normalizeValidateRules(
validate, // 收集驗證規則字段存儲
rules, // 字段驗證規則
validateTrigger // 觸發字段驗證規則事件數組
) {
var validateRules = validate.map(function (item) {
var newItem = _extends({}, item, {
trigger: item.trigger || [],
});
if (typeof newItem.trigger === "string") {
newItem.trigger = [newItem.trigger];
}
return newItem;
});
console.log("validateRules=", validateRules);
// 如果該字段有驗證規則澤添加到validateRules隊列中
if (rules) {
validateRules.push({
trigger: validateTrigger ? [].concat(validateTrigger) : [],
rules: rules,
});
}
console.log("validateTrigger=", validateTrigger);
console.log("validateRules=", validateRules);
return validateRules;
}
getValidateTriggers
-
從normalizeValidateRules 中獲取到的validateRules過濾成一個數組只要item.trigger屬性該屬性一般為onChange事件。
-
通過獲取到的trigger和validateTriggers來判斷然后調用getCacheBind去給form表單組件綁定onChange事件和校驗器。
-
如果trigger && validateTriggers.indexOf(trigger) === -1 則表示當前form表單 並沒有rules校驗器。然后調用getCacheBind綁定onCollectCommon 函數 dom從原生獲取值。 並且返回value值,name,fieldMeta。
-
而trigger && validateTriggers.indexOf(trigger) !== -1 則表示當前form表單 有rules校驗器。 的情況下onCollectValidate dom從原生獲取值。 並且返回value值,name,fieldMeta,並且校驗字段。
function getValidateTriggers(validateRules) {
return validateRules
.filter(function (item) {
//過濾數據
return !!item.rules && item.rules.length;
})
.map(function (item) {
//只要獲取trigger 一般為change
return item.trigger;
})
.reduce(function (pre, curr) {
// 連接數組
return pre.concat(curr);
}, []);
}
getCacheBind 綁定onChange事件,並且返回事件對象
// 組件事件綁定等 這里一般指的是收集onChange事件,然后返回事件對象
getCacheBind: function getCacheBind(name, action, fn) {
// 判斷有沒有綁定緩存,如果沒有則先給一個空的對象
if (!this.cachedBind[name]) {
this.cachedBind[name] = {};
}
// 獲取緩存
var cache = this.cachedBind[name];
//如果獲取不到緩存那么就設置緩存
if (!cache[action] || cache[action].oriFn !== fn) {
cache[action] = {
// 事件固定傳參
fn: fn.bind(this, name, action),
oriFn: fn,
};
}
//返回緩存中的fn函數
return cache[action].fn;
},
onCollectValidate 收集驗證 onchange 事件
-
調用onCollectCommon 方法去調用onChange事件
-
調用validateFieldsInternal 做校驗並且調用 setFields 設置字段值
// 收集驗證 onchange 事件
onCollectValidate: function onCollectValidate(name_, action) {
console.log("arguments=", arguments);
console.log("onCollectValidate===========");
for (
var _len2 = arguments.length,
args = Array(_len2 > 2 ? _len2 - 2 : 0),
_key2 = 2;
_key2 < _len2;
_key2++
) {
// 收集大於2個參數組成數組存放在args數組中
args[_key2 - 2] = arguments[_key2];
}
// 收集設置字段 從事件中獲取值 和從事件中設置值
var _onCollectCommon2 = this.onCollectCommon(name_, action, args),
// 獲取字段
field = _onCollectCommon2.field,
// 獲取字段存儲的對象
fieldMeta = _onCollectCommon2.fieldMeta;
// 新的字段
var newField = _extends({}, field, {
dirty: true, //檢查校驗字段 標志dirty 為true
});
// 檢查校驗字段 標志dirty 為true
this.fieldsStore.setFieldsAsDirty();
//內部驗證字段
this.validateFieldsInternal([newField], {
action: action,
options: {
firstFields: !!fieldMeta.validateFirst, //當某一規則校驗不通過時,是否停止剩下的規則的校驗
},
});
},
onCollectCommon 收集 事件中獲取值
-
onCollectCommon 收集 事件中獲取值 ,調用onChange事件,返回name,field,fieldMeta 對象
-
onCollectCommon: function onCollectCommon(
name, // 字段名稱
action, // 事件
args // 事件event 參數
) {
// 獲取單個字段的getFieldMeta 對象 這個是字段 信息 和設置 Meta 初始化值作用
var fieldMeta = this.fieldsStore.getFieldMeta(name);
console.log('fieldMeta=',fieldMeta)
console.log('action=',fieldMeta)
// 判斷fieldMeta 中有 事件么 如果有有則執行事件
if (fieldMeta[action]) {
// 執行onChange方法
fieldMeta[action].apply(
fieldMeta,
// 數組去重
_toConsumableArray(args)
);
} else if (
//原始組件的的props 屬性
fieldMeta.originalProps &&
//原始組件的的props 屬性 事件
fieldMeta.originalProps[action]
) {
var _fieldMeta$originalPr;
// 執行onChange
(_fieldMeta$originalPr = fieldMeta.originalProps)[action].apply(
_fieldMeta$originalPr,
// 數組去重
_toConsumableArray(args)
);
}
//從原生dom onChange事件中獲取值
var value = fieldMeta.getValueFromEvent
? fieldMeta.getValueFromEvent.apply(
fieldMeta,
// 數組去重
_toConsumableArray(args)
)
: getValueFromEvent.apply(
undefined,
// 數組去重
_toConsumableArray(args)
);
// 如果表單有傳遞onValuesChange 函數進來 則觸發
if (onValuesChange && value !== this.fieldsStore.getFieldValue(name)) {
// 獲取所有值
var valuesAll = this.fieldsStore.getAllValues();
var valuesAllSet = {};
valuesAll[name] = value;
// 循環所有值
Object.keys(valuesAll).forEach(function (key) {
//設置值
return set(valuesAllSet, key, valuesAll[key]);
});
// 更新值
onValuesChange(
// 淺拷貝
_extends(
// 為對象添加 描述設置屬性 或者是為對象添加 屬性或者方法
_defineProperty({}, formPropName, this.getForm()),
this.props
),
// 設置值
set({}, name, value),
// 原來所有值對象
valuesAllSet
);
}
// 獲取字段
var field = this.fieldsStore.getField(name);
return {
// 字段名稱
name: name,
// 合並新的字段
field: _extends({}, field, { value: value, touched: true }),
// 字段存儲對象
fieldMeta: fieldMeta,
};
}, -
validateFieldsInternal
-
驗證字段函數
-
收集驗證 onchange 事件 ,調用 "async-validator"校驗插件,收集是否有error信息,然后存儲到fieldMeta對象中。
-
然后調用調用 setFields 設置字段值
//字段內部驗證字段
validateFieldsInternal: function validateFieldsInternal(
fields, // 需要校驗的字段
_ref, // 拓展參數選項
callback // 回調函數
) {
var _this7 = this;
var fieldNames = _ref.fieldNames, // 字段名稱
action = _ref.action, // 字段事件 一般為onchange
_ref$options = _ref.options, // getFieldDecorator 參數
options = _ref$options === undefined ? {} : _ref$options;
var allRules = {}; // 校驗規則
var allValues = {}; // 值
var allFields = {}; //字段
var alreadyErrors = {}; // 錯誤信息
// 循環字段
fields.forEach(function (field) {
// 獲取字段名稱
var name = field.name;
if (options.force !== true && field.dirty === false) {
// 字段錯誤信息
if (field.errors) {
// 如果有錯誤信息存起來
set(alreadyErrors, name, { errors: field.errors });
}
return;
}
// 獲取單個字段的getFieldMeta 對象 這個是字段 信息 和設置 Meta 初始化值作用
var fieldMeta = _this7.fieldsStore.getFieldMeta(name);
//淺拷貝字段
var newField = _extends({}, field);
//設置新的字段錯誤信息為undefined
newField.errors = undefined;
// 設置已經驗證過
newField.validating = true;
//
newField.dirty = true;
//獲取得到驗證規則
allRules[name] = _this7.getRules(fieldMeta, action);
// 獲取值
allValues[name] = newField.value;
//字段名稱
allFields[name] = newField;
});
// 設置字段
this.setFields(allFields);
// in case normalize 以防正常化 獲取全部值
Object.keys(allValues).forEach(function (f) {
// 獲取值
allValues[f] = _this7.fieldsStore.getFieldValue(f);
});
//判斷對象是否是空對象
if (callback && isEmptyObject(allFields)) {
callback(
isEmptyObject(alreadyErrors) ? null : alreadyErrors,
// 字段值
this.fieldsStore.getFieldsValue(fieldNames)
);
return;
}
// 表單異步驗證插件
var validator = new AsyncValidator(allRules);
//整個表單校驗信息 一般不會傳遞這個
if (validateMessages) {
validator.messages(validateMessages);
}
console.log('allRules=',allRules)
console.log('allValues=',allValues)
validator.validate(
allValues, // 全部值
options, // 選項
// 錯誤信息回調函數
function (errors) {
// 獲取錯誤信息集合
var errorsGroup = _extends({}, alreadyErrors);
// 如果錯誤信息存在
if (errors && errors.length) {
// 循環錯誤信息
errors.forEach(function (e) {
//獲取字段
var errorFieldName = e.field;
var fieldName = errorFieldName;
// Handle using array validation rule. 句柄使用數組驗證規則。
// ref: https://github.com/ant-design/ant-design/issues/14275
//如果有一個元素滿足條件,則表達式返回true , 剩余的元素不會再執行檢測。
Object.keys(allRules).some(function (ruleFieldName) {
var rules = allRules[ruleFieldName] || [];
// Exist if match rule 如果匹配規則存在
if (ruleFieldName === errorFieldName) {
fieldName = ruleFieldName;
return true;
}
// Skip if not match array type 如果不匹配數組類型,則跳過
if (
//如果全部元素滿足條件,則表達式返回true ,
rules.every(function (_ref2) {
var type = _ref2.type;
return type !== "array";
}) ||
// 檢查 xxx.
errorFieldName.indexOf(ruleFieldName + ".") !== 0
) {
return false;
}
// Exist if match the field name 如果匹配字段名稱,則存在
var restPath = errorFieldName.slice(ruleFieldName.length + 1);
if (/^\d+$/.test(restPath)) {
fieldName = ruleFieldName;
return true;
}
return false;
});
// 獲取字段
var field = get(errorsGroup, fieldName);
if (typeof field !== "object" || Array.isArray(field)) {
// 記錄錯誤字段
set(errorsGroup, fieldName, { errors: [] });
}
var fieldErrors = get(errorsGroup, fieldName.concat(".errors"));
//收集錯誤信息
fieldErrors.push(e);
});
}
var expired = [];
var nowAllFields = {};
// 循環校驗規則
Object.keys(allRules).forEach(function (name) {
//獲取錯誤字段
var fieldErrors = get(errorsGroup, name);
// 獲取當前字段
var nowField = _this7.fieldsStore.getField(name);
// avoid concurrency problems 避免並發問題
//判斷兩個值是否相等
if (!eq(nowField.value, allValues[name])) {
// 如果不相等
expired.push({
name: name,
});
} else {
//如果相等
nowField.errors = fieldErrors && fieldErrors.errors;
nowField.value = allValues[name];
nowField.validating = false;
nowField.dirty = false;
nowAllFields[name] = nowField;
}
});
// 設置字段
_this7.setFields(nowAllFields);
if (callback) {
//如果有值不相等,則需要重新校驗一次
if (expired.length) {
expired.forEach(function (_ref3) {
var name = _ref3.name;
var fieldErrors = [
{
message: name + " need to revalidate", //需要重新驗證
field: name,
},
];
// 記錄是否有錯誤信息
set(errorsGroup, name, {
expired: true,
errors: fieldErrors,
});
});
}
// 回調函數
callback(
isEmptyObject(errorsGroup) ? null : errorsGroup,
_this7.fieldsStore.getFieldsValue(fieldNames)
);
}
}
);
},
setFields 設置form表單值
-
參數:對象key與value。重新設置表單值,
-
通過循環遍歷form表單值新舊值對比,如果不同則更新
function setFields(fields) {
var _this = this;
// 獲取字段信息
var fieldsMeta = this.fieldsMeta;
// 新字段 和 原來字段合並
var nowFields = _extends({}, this.fields, fields);
// 新的值
var nowValues = {};
// 獲取字段值
Object.keys(fieldsMeta).forEach(function (f) {
// 獲取字段的值
nowValues[f] = _this.getValueFromFields(
f, // 字段名稱
nowFields // 所有字段
);
});
// 循環現在的值 然后注冊到Meta 中
Object.keys(nowValues).forEach(function (f) {
// 獲取單個值
var value = nowValues[f];
// 獲取單個字段的getFieldMeta 對象 這個是字段 信息
var fieldMeta = _this.getFieldMeta(f);
// 初始化值設定的一個函數 demo https://codepen.io/afc163/pen/JJVXzG?editors=0010
if (fieldMeta && fieldMeta.normalize) {
// 獲取字段的值
//當前值
var nowValue = fieldMeta.normalize(
value,
_this.getValueFromFields(f, _this.fields),
nowValues
);
//如果新的值和舊的值不相同則更新新的值
if (nowValue !== value) {
nowFields[f] = _extends({}, nowFields[f], {
value: nowValue,
});
}
}
});
console.log('this.fields=', this.fields)
debugger
// 設置 字段
this.fields = nowFields;
},
validateFields 表單提交 校驗所有表單值。
-
表單提交前做做校驗。
-
獲取到參數通過getParams格式處理參數,這樣讓函數接口兼容性更強
-
然后調用validateFieldsInternal去做校驗
-
callback 返回表單值
//驗證字段,返回promise
validateFields: function validateFields(ns, opt, cb) {
var _this8 = this;
console.log("this=", this);
console.log("this.fieldsStore=", this.fieldsStore);
var pending = new Promise(function (resolve, reject) {
// 得到參數,格式化整理轉義參數
var _getParams = getParams(ns, opt, cb),
// 獲取參數的names
names = _getParams.names,
// 獲取參數的options 選項
options = _getParams.options;
// 得到參數,格式化整理轉義參數
var _getParams2 = getParams(ns, opt, cb),
// 獲取參數的回調函數
callback = _getParams2.callback;
// 如果回調函數
if (!callback || typeof callback === "function") {
var oldCb = callback;
callback = function callback(errors, values) {
if (oldCb) {
// 執行回調函數
oldCb(errors, values);
}
if (errors) {
// 如果有錯誤則執行reject
reject({ errors: errors, values: values });
} else {
// 成功執行
resolve(values);
}
};
}
// 獲取字段名稱 從所有字段中 過濾出 maybePartialName 參數匹配到的字段
var fieldNames = names
? _this8.fieldsStore.getValidFieldsFullName(names)
: _this8.fieldsStore.getValidFieldsName();
// 獲取含有檢驗規則的字段
var fields = fieldNames
.filter(function (name) {
// 獲取單個字段的getFieldMeta 對象 這個是字段 信息 和設置 Meta 初始化值作用
var fieldMeta = _this8.fieldsStore.getFieldMeta(name);
//含有校驗規則的字段
return hasRules(fieldMeta.validate);
})
.map(function (name) {
//獲取字段
var field = _this8.fieldsStore.getField(name);
// 獲取字段的值
field.value = _this8.fieldsStore.getFieldValue(name);
// 返回字段
return field;
});
console.log("validateFields fields=", fields);
// 如果沒有校驗字段
if (!fields.length) {
// 獲取字段值
callback(null, _this8.fieldsStore.getFieldsValue(fieldNames));
return;
}
// 標志當某一規則校驗不通過時,是否停止剩下的規則的校驗
if (!("firstFields" in options)) {
options.firstFields = fieldNames.filter(function (name) {
// 獲取單個字段的getFieldMeta 對象 這個是字段 信息 和設置 Meta 初始化值作用
var fieldMeta = _this8.fieldsStore.getFieldMeta(name);
return !!fieldMeta.validateFirst; //當某一規則校驗不通過時,是否停止剩下的規則的校驗
});
}
//字段校驗
_this8.validateFieldsInternal(
fields,
{
fieldNames: fieldNames,
options: options,
},
callback
);
});
//俘獲錯誤
pending["catch"](function (e) {
// eslint-disable-next-line no-console
if (console.error && process.env.NODE_ENV !== "production") {
// eslint-disable-next-line no-console
console.error(e);
}
return e;
});
return pending;
}, -