Geo*_*nko 13 javascript forms ajax jquery reactjs
我正在为react.js中的web-app重写UI,我对以下问题感到有些困惑.
我有一个页面显示通过AJAX请求获得的数据,在下面显示一个提交新数据的表单.都好.
现在,我想<select>
在表单中添加一个元素,并从不同的位置(url)获取值.
当前代码(没有<select>
)看起来像这样(简化了一点,但所有工作细节都相同;它主要遵循react.js网站上的教程):
var tasks_link = $('#tasks_link');
var getDataMixin = {
loadDataFromServer: function() {
$.ajax({
url: this.props.url,
dataType: 'json',
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
getInitialState: function() {
return {data: []};
},
componentDidMount: function() {
this.loadDataFromServer();
}
};
var sendDataMixin = {
handleDataSubmit: function(senddata) {
$.ajax({
url: this.props.url,
dataType: 'json',
contentType: 'application/json',
type: 'POST',
data: senddata,
success: function(data) {
var curr_d = this.state.data;
var curr_d_new = curr_d.concat([data]);
this.setState({data: curr_d_new});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
}
};
var taskForm = React.createClass({
handleSubmit: function() {
var name = this.refs.task_name.getDOMNode().value.trim();
if (!name) {
return false;
}
this.props.onTaskSubmit(JSON.stringify({name: name}));
this.refs.task_name.getDOMNode().value = '';
return false;
},
render: function () {
return (
<form className="well base_well new_task_well" onSubmit={this.handleSubmit}>
<div className="form-group">
<div className="input-group">
<span className="input-group-addon no_radius">Task name</span>
<input type="text" className="form-control no_radius" id="add_new_project_input" ref="task_name"/>
</div>
</div>
<button type="button" className="btn btn-default no_radius add_button" id="add_new_task_btn" type="submit">Add task</button>
</form>
);
}
});
var taskBox = React.createClass({
mixins: [getDataMixin, sendDataMixin],
render: function () {
return (
<div id="project_box" className="taskBox"> <taskList data={this.state.data} />
<taskForm onTaskSubmit={this.handleDataSubmit}/> </div>
);
}
});
tasks_link.click(function() {
React.renderComponent(
<taskBox url="/api/tasks/" />,
document.getElementById('content_container')
);
});
Run Code Online (Sandbox Code Playgroud)
现在,我可以添加select
的元素添加getDataMixin
到TaskForm
,获取数据和构建可能的选项的列表,但我需要有很多的列表形式,这种方法似乎并没有按比例(由于命名冲突;或我需要使用除mixins之外的东西).
所以我虽然创建了一个单独的React class
,只需要getDataMixin
通过父设置接收API url props
,然后渲染<select>
元素; 并在表单中使用此类.但我不知道如何访问所选值(因为父母无法访问它的孩子refs
).所以我需要另一种方法来传递选定的值"up".
或者,如果这是不可能的,在正确的方向轻推 - 我不想最终得到大量不可重用的代码(我切换到反应的部分原因是使用mixins并保持代码以理智和可读的最小值).
Mik*_*ver 17
只要您将子项设置为父项中的ref,父项就可以访问其子项的引用,您可以访问该子项中的任何引用.所以例如像this.refs.childRef.refs.nestedChildRef
.然而,这是一个非常糟糕的主意,除非您只是阅读信息(并处理错误,例如refs不正确,因为父母不知道孩子的ref是否设置正确).
但幸运的是,有一个非常简单的解决方案.你是对的,你会想要创建一个子组件来获取它自己的数据,而不是mixin.但是你如何处理将所选项目返回给父项只是简单地从父项传递一个onChange函数,就像你对内置<select>
的反应一样.
以下是此父子关系的示例:
var MyParent = React.createClass({
getInitialState: function() {
return {
childSelectValue: undefined
}
},
changeHandler: function(e) {
this.setState({
childSelectValue: e.target.value
})
},
render: function() {
return (
<div>
<MySelect
url="http://foo.bar"
value={this.state.childSelectValue}
onChange={this.changeHandler}
/>
</div>
)
}
});
var MySelect = React.createClass({
propTypes: {
url: React.PropTypes.string.isRequired
},
getInitialState: function() {
return {
options: []
}
},
componentDidMount: function() {
// get your data
$.ajax({
url: this.props.url,
success: this.successHandler
})
},
successHandler: function(data) {
// assuming data is an array of {name: "foo", value: "bar"}
for (var i = 0; i < data.length; i++) {
var option = data[i];
this.state.options.push(
<option key={i} value={option.value}>{option.name}</option>
);
}
this.forceUpdate();
},
render: function() {
return this.transferPropsTo(
<select>{this.state.options}</select>
)
}
});
Run Code Online (Sandbox Code Playgroud)
上面的示例显示了一个父组件,它MyParent
包含一个子组件MySelect
,它传递一个url,以及对标准react <select>
元素有效的任何其他props .使用react的内置this.transferPropsTo()
函数将所有道具转移到<select>
其渲染函数中的子元素.
这意味着定义changeHandler
为onChange
处理程序的父级MySelect
将此函数直接传递给子<select>
元素.因此,当select更改时,事件由父级而不是子级处理.顺便说一句,这是在React中做事的完美合法和合法的方式 - 因为它仍然遵循自上而下的哲学.如果你考虑一下,当你使用一个普通的内置<select>
反应时,这就是正在发生的事情. onChange
只是一个属性<select>
.
值得注意的是,如果您愿意,可以"混合"更改处理程序以添加您自己的自定义逻辑.例如,我倾向于<input type="text" />
使用自定义输入组件包装我的字段,该组件接受任何和所有有效的<input>
道具,但也将validator
函数作为一个属性,允许我根据输入的值定义返回true/false的函数.这个<input>
领域.我可以通过onChange
在父对象中为包装子进行定义来做到这一点,但是在子进程中我定义了我自己的onChange
内部检查this.props.onChange
要定义的函数,然后运行一个函数,然后运行我的验证器并将事件链传递回父进程通过电话this.props.onChange(e, valid)
.在父onChange
程序的处理程序中为父项提供相同的事件对象,但也添加了一个布尔valid
参数.无论如何,我离题....
希望这可以帮助你 :)
归档时间: |
|
查看次数: |
36677 次 |
最近记录: |