informed的源碼有三個(gè)重點(diǎn): FormController和FieldController以及withFieldStuff函數(shù)。他們的關(guān)系如下所示:

FormController
FormController是核心。它有三個(gè)屬性: values,field,以及errors。values和errors的數(shù)據(jù)類(lèi)型ObjectMap(為什么要用這個(gè)數(shù)據(jù)格式我沒(méi)有搞懂),field是map類(lèi)型,一個(gè)fieldName綁定一個(gè)對(duì)應(yīng)的fieldController。FormController 繼承EventEmitter,繼承這個(gè)庫(kù)在以下功能中都有用到。這里主要介紹setValue/getValue/register方法
ObjectMap
ObjectMap的數(shù)據(jù)類(lèi)型有三個(gè)屬性:objects, map,path。path的格式是這樣的
{
'a.b.c':[a,b,c],
'a.b[1]':[a, b, 1]
}
objects就是fieldName和value的一一對(duì)應(yīng),比如:
{
a:{
b:{
c: 'hello'
}
}
}
map的數(shù)據(jù)格式如下所示

這個(gè)class有還有get和set方法。基本上就是遍歷設(shè)置和獲取對(duì)應(yīng)field的值。
這里我有一個(gè)疑問(wèn)了,我刷了整個(gè)informed的方法,用到map的寥寥無(wú)幾,這個(gè)屬性有存在的必要嗎?
values
values中存儲(chǔ)的是每一個(gè)包含在form表單中組件的值。它是一個(gè)特殊的數(shù)據(jù)格式(ObjectMap)
和這個(gè)屬性相關(guān)的有兩個(gè)函數(shù): setValue和getValue,顧名思義。
-
setValue
setValue的代碼如下:
this.values.set(
field,
fieldController.config.mask ? fieldController.config.mask(value) : value
);
...
this.emit('change', this.state);
this.emit('values', this.state.values);
this.emit('field', field);
重點(diǎn)是這三個(gè)事件change,values和field。那么接收change事件調(diào)用的函數(shù)在Form組件中的constructor
this.controller.on('change', () => this.forceUpdate());
調(diào)用的是react的forceUpdate方法。會(huì)讓form下的所有子組件重新渲染。
接收field事件的函數(shù),是在withFieldStuff函數(shù)中。
const buildFieldState = (formApi, field) => {
return {
value: formApi.getValue(field),
touched: formApi.getTouched(field), //touch并不知道干嘛用的
error: formApi.getError(field),
asyncError: formApi.getAsyncError(field)
};
};
....
const updateMe = name => {
if (name === formApi.getFullField(field)) {
//重新獲取field對(duì)應(yīng)新的value的值
this.setState(buildFieldState(formApi, field));
}
};
controller.on('field', updateMe);
以上代碼,當(dāng)接收到field事件時(shí),每一個(gè)包裹Field的input,都會(huì)從FormController中重新獲取當(dāng)前field的最新的值。
FieldController
FieldController的代碼如下所示:
class FieldController {
constructor(field, api, config) {
this.field = field;
this.config = config;
this.api = api;
}
validate(values) {
if (this.config.validate) {
return this.config.validate(this.api.getValue(), values);
}
}
asyncValidate(values) {
if (this.config.asyncValidate) {
return this.config.asyncValidate(this.api.getValue(), values);
}
}
updateConfig(config) {
this.config = config;
}
}
FieldController主要對(duì)傳入的this.config.validate函數(shù)進(jìn)行一層封裝。創(chuàng)建FieldController函數(shù)的代碼如下所示:
this.fieldController = new FieldController(
formApi.getFullField(field),
this.fieldApi,
{
validateOnBlur,
validateOnChange,
validate,
onValueChange,
asyncValidate,
asyncValidateOnBlur,
initialValue,
validateOnMount,
notify,
mask
}
);
在Field初始化時(shí)(constructor ),會(huì)為每一個(gè)field創(chuàng)建一個(gè)controller。
那什么時(shí)候使用這個(gè)constroller的valiate函數(shù)呢?在formController的setValue和setTouched函數(shù)都有,前提要配置一些參數(shù)
setValue函數(shù)中的,如果配置了validateOnChange
...
if (fieldController.config.validateOnChange) {
this.errors.set(field, fieldController.validate(this.state.values));
// We changed so notify all other fields
this.notify(fieldController.config.notify);
}
...
setTouched函數(shù),如果配置了validateOnBlur
if (fieldController.config.validateOnBlur) {
this.errors.set(field, fieldController.validate(this.state.values));
// We changed so notify all other fields
this.notify(fieldController.config.notify);
}
withFieldStuff函數(shù)
withFieldStuff函數(shù)是連接FieldController和FormController之間的橋梁。同時(shí)也從formApi中獲取本field相關(guān)的函數(shù)和值。主要的函數(shù)是register函數(shù)。該函數(shù)會(huì)在Field組件componentDidMount中調(diào)用
class Field extends PureComponent {
constructor(props) {
super(props);
this.me = React.createRef();
}
componentDidMount() {
this.props.register();
}
}
接下來(lái)看register函數(shù)的流程。

整個(gè)informed源碼的重點(diǎn)部分就說(shuō)完了
問(wèn)題:
1.如果我在組件A中需要用到組件B的值?(這個(gè)在表單中非常常見(jiàn))
2.作者創(chuàng)建一個(gè)objectMap數(shù)據(jù)類(lèi)型意義何在?
以后的話:
我看的這個(gè)版本的informed源碼是比較老。新的版本又出了,使用了hook的技術(shù)。所以這個(gè)系列未完待續(xù)。
`