Javascript 从使用react native中的map函数渲染的组件的父级调用子方法
我正在构建一个表单,该表单根据字段的json定义插入字段。json对象被解析并传递到一个switch语句,该语句选择一个合适的小部件并将其插入数组。该数组被排序,然后使用数组映射呈现 我需要实现的是在按下submit后调用每个字段的validate字段现在如何访问这些元素调用适当的validate逻辑 到目前为止我所尝试的Javascript 从使用react native中的map函数渲染的组件的父级调用子方法,javascript,react-native,redux,react-redux,Javascript,React Native,Redux,React Redux,我正在构建一个表单,该表单根据字段的json定义插入字段。json对象被解析并传递到一个switch语句,该语句选择一个合适的小部件并将其插入数组。该数组被排序,然后使用数组映射呈现 我需要实现的是在按下submit后调用每个字段的validate字段现在如何访问这些元素调用适当的validate逻辑 到目前为止我所尝试的 将小部件推入数组时使用refs 与在渲染函数外部指定参照相关的抛出错误 将对map的调用包装在引用的视图中,并通过this.refs[“myWrapper].props.ch
this.refs[“myWrapper].props.children
这种方法允许我访问我的小部件,但返回的对象不包含我的方法,因此调用它们不会为函数抛出错误constructor(props){
super(props);
this.fields=[];
}
getFields(fields){
let {formName,title}=this.props;
let field,_fields=[],item;
fields= this.sortFieldsOrder(fields);
fields.forEach((sect,i)=>{
for(field in sect)
{
item=sect[field];
switch (item.widget){
case "inlineText":
_fields.push(
<EbTextInput key={field}
{...{...item.props,formName,title}}
field={field}
label={item.hasOwnProperty("label")?item.label:""}
validator={item.hasOwnProperty("validator")?item.validator:()=>{}}
/>
);
break;
case "hidden":
_fields.push(
<EbHiddenInput key={field}
{...{...item.props,formName,title}}
field={field}
label={item.hasOwnProperty("label")?item.label:""}
validator={item.hasOwnProperty("validator")?item.validator:()=>{}}
/>
);
break;
case"modal":
_fields.push(
<EbModalInput
key={field}
{...{...item.props,formName,title}}
field={field}
fields={item.props.fields instanceof Array?this.getFields(item.props.fields):[]}
label={item.hasOwnProperty("label")?item.label:""}
validator={item.hasOwnProperty("validator")?item.validator:()=>{}}
/>
);
break;
case"filePicker":
let picker=<EbFilePickerInput key={field}
{...{...item.props,formName,title}}
field={field}
label={item.hasOwnProperty("label")?item.label:""}
validator={item.hasOwnProperty("validator")?item.validator:()=>{}}
/>;
picker=[picker];
_fields.push(
<EbModalInput key={field}
{...{...item.props,formName,title}}
field={field}
fields={picker}
label={item.hasOwnProperty("label")?item.label:""}
validator={item.hasOwnProperty("validator")?item.validator:()=>{}}
/>
);
break;
case "option":
_fields.push(
<EbOptionInput
key={field}
{...{...item.props,formName,title}}
field={field}
fields={item.props.fields instanceof Array?this.getFields(item.props.fields):[]}
label={item.hasOwnProperty("label")?item.label:""}
validator={item.hasOwnProperty("validator")?item.validator:()=>{}} />
);
break;
default:
}
}
});
return _fields;
}
sortFieldsOrder(arr){
return arr.sort((a,b)=>{
let keyA=Object.keys(a)[0];
let keyB=Object.keys(b)[0];
if(a[keyA]["order"]<b[keyB]["order"])return 1;
if(a[keyA]["order"]>b[keyB]["order"])return -1;
return 0;
});
}
componentWillMount(){
let {fields}=this.props;
this.fields=this.getFields(fields)
}
renderFields(){
return this.fields.map((item)=>{
return item;
})
}
validateForm(){
let field;
let fields=this.refs["wrapper"].props.children;
let status=true;
React.Children.map(this.refs["wrapper"].props.children, (child) => {
if(!child.validate()){
status= false;
console.log("valid form cheki");
// break;
}
})
return status;
}
render(){
return(
<View ref="wrapper" style={[styles.flex1]}>
{this.renderFields()}
<Button text="Submit" onPress={(e)=>{
if(this.validateForm()){
//alert("valid form")
}
else
alert("invalid form")
}}> </Button>
</View>)
}
构造函数(道具){
超级(道具);
this.fields=[];
}
getFields(字段){
设{formName,title}=this.props;
let字段,_字段=[],项;
字段=此.sortFieldsOrder(字段);
fields.forEach((sect,i)=>{
用于(节中的字段)
{
项目=节[字段];
开关(item.widget){
案例“inlineText”:
_推(
{}}
/>
);
打破
案例“隐藏”:
_推(
{}}
/>
);
打破
“情态”一案:
_推(
{}}
/>
);
打破
案例“文件选择器”:
让选取器={}
/>;
选择器=[picker];
_推(
{}}
/>
);
打破
案例“选项”:
_推(
{}} />
);
打破
违约:
}
}
});
返回_字段;
}
sortFieldsOrder(arr){
返回arr.sort((a,b)=>{
设keyA=Object.keys(a)[0];
设keyB=Object.keys(b)[0];
如果(a[keyA][“订单”]b[keyB][“订单”])返回-1;
返回0;
});
}
组件willmount(){
设{fields}=this.props;
this.fields=this.getFields(字段)
}
renderFields(){
返回此.fields.map((项)=>{
退货项目;
})
}
validateForm(){
让场;
让fields=this.refs[“wrapper”].props.children;
让status=true;
React.Children.map(this.refs[“wrapper”].props.Children,(child)=>{
如果(!child.validate()){
状态=假;
console.log(“有效形式cheki”);
//中断;
}
})
返回状态;
}
render(){
返回(
{this.renderFields()}
{
if(this.validateForm()){
//警报(“有效形式”)
}
其他的
警报(“无效表单”)
}}>
)
}
}
`在react中,无论出于何种原因,直接访问节点都是ant模式,因此我决定使用redux继续上面的第一条评论,我可以发送一个验证信号,让每个小部件验证自己的状态,这减少了耦合,易于实现和调试,因此我建议所有有相同问题的人都遵循这一点ass实际上,您可以在您的案例中使用refs,但与其通过调用
componentWillMount
中的getFields
来生成子组件,不如直接在render
方法中调用它。换句话说,不需要使用this.fields
,您可以直接渲染它们。只要您有correct键,React将正确管理缓存。父对象不调用子方法。父对象传递其子对象的道具。如果父对象希望在组件层次结构中发出更改信号,则传递其子对象(ren)一组新的道具。因此,您建议我传递一些道具,可能使用redux触发验证逻辑。这将很简单,也更合法。感谢您的评论,我只想让问题停留更长时间,看看是否有不同的视图。我希望避免在每个渲染上重复字段,这就是为什么会出现组件中的.fieldsWillMountIterating on fields实际上比渲染便宜,尽管您缓存了组件,但如果重新渲染,无论您是否重新迭代字段,成本都不会有很大不同,除非您有大量字段,例如超过1000个。其次,由于您的组件看起来是无状态的,因此不会太频繁地重新渲染,而不是迭代不会经常发生。简言之,我建议将所有组件生成部分放入渲染流中,而不是缓存组件。某些机制,例如ref绑定,依赖于此。是的,在几个字段上迭代很便宜,但需要迭代三次,第一次排序,第二次获取表单上的第三个字段验证和在模态小部件中,它遵循相同的模式,因此它将有自己的子小部件,需要排序和获取字段,这使我决定在装载前执行所有这些操作,以防我流氓并放入数百个字段。如果需要,您仍然可以缓存排序结果,我的意思是不要缓存组件,cac他改为使用数据结构。