临时上阵开发一个基于React+AntD的工具项目,没有系统化的学习过,只能开发过程中碰到问题解决问题,走一步看一步
这是来自我们前端同学的建议,如果有过前端开发经验,想快速上手React开发做一些简单交互项目,需要:
1.把ECMAScript6的教程看一遍:http://es6.ruanyifeng.com/#docs/intro
2.把React的基本教程看一遍,尤其了解JSX、组件、state、Props:http://www.runoob.com/react/react-tutorial.html
3.熟悉一些工程化工具:脚手架、webpack、ESLint
不学ECMAScript6,有Javascript基础的话,直接上手React做一些简单页面开发并没有问题,但如果想把代码写好,ES6必须研究透
ES6重点学习变量的结构赋值,否则写出来的代码无法ESLint的规范
注:下面的范例代码很多没有遵守ESLint的规则
下面是我在React&AndD的遇到一些问题的学习笔记和总结,将持续更新记录:
一、React向事件处理函数传参:
- 对比传统js:
Function定义:
function onClickHandler(uid){
console.log(uid);
}
控件上绑定onClick事件,并传参uid
<a href="" onClick = 'onClickHandler(uid)' />
- React中:
Function定义:
onClickHandler = (uid) => {
console.log(uid);
}
控件上绑定onClick事件,并传参uid
<a href="" onClick = {this.onClickHandler.bind(this,uid)}/>
或者
<a href="" onClick = {e => this.onClickHandler(uid,e)}/>
二、调用后台接口
使用ajax
$.ajax(
{
url: "/recruit/data/remove",
contentType: 'application/json; charset=utf-8',
type: 'POST',
dataType: 'json',
data: data,
cache: false,
success: function (ret) {
this.setState({ retData: ret })
this.setModalVisilble(true);
}.bind(this),
error: function (xhr, status, err) { }.bind(this)
}
)
三、模块间数据传输(props/ref的使用)
父组件通过props向子组件传值,在父组件中刷新props中的属性值,就可以实现对子组件的数据刷新。
场景:点击按钮打开一个Modal,Modal中有一个Form,点击按钮时需要传递一个ref_id给Modal中的Form,Form提交时需要用到。
1.定义子组件Form
const FormItem = Form.Item;
class Child extends Component {
constructor(props) {
super(props);
}
render() {
const { getFieldDecorator } = this.props.form;
const id = this.props.id; // 通过props获取父组件传递的值
return (
<div>
<Form>
<FormItem>
{getFieldDecorator('id', { rules: [{ required: true, message: 'Please Input Id!' }] })
(<Input />)
}
</FormItem>
</Form>
</div>
)
}
}
const WrappedChild = Form.create()(Child);
export default WrappedChild;
2.父组件中传递ref_id到state.id,Form通过props获取ref_id
class Father extends Component {
onClickHandler = (ref_id, e) => {
// 父组件的ref_id = 1赋值给state.ref_id
this.setState({ ref_id: ref_id })
this.setState({ visible: true })
}
onOkHandler = (e) => {
let child = this.refs.child
child.validateFields((err, values) => {
e.preventDefault();
// 刷新state.ref_id,也就刷新了ref_Form.props.id
this.setState({ret_id:2});
// 父组件直接读写操作child.props.id是不允许的(可以理解为子组件的私有属性),会报Cannot read property 'props' of undefined
child.props.id = 3
})
}
render() {
<div>
<a href="javascript:;" onClick={e => this.onClickHandler(ref_id, e)} />
<Modal
title="请输入参数"
visible={this.state.visible}
onOk={this.onOkHandler}
onCancel={this.onCancelHandler}>
// 子组件通过props将ref_id传递
<WrappedChild ref="child" id={this.state.ref_id} />
</Modal>
</div>
}
}
子组件向父组件传值
场景:子组件中Form表单的数据需要传递给父组件,在父组件中进行提交
1.子组件:
const FormItem = Form.Item;
class Child extends Component {
constructor(props) {
super(props);
this.state = {istrue:false}
}
istrueChange = (e) => {
this.setState({istrue:e.target.checked})
// 通过调用回调函数的方式实现传递值到父组件
this.props.istrue(e.target.checked)
}
render() {
const { getFieldDecorator } = this.props.form;
const id = this.props.id; // 通过props获取父组件传递的值
return (
<div>
<Form>
<FormItem>
{getFieldDecorator('id', { rules: [{ required: true, message: 'Please Input Id!' }] })
(<Input />)
}
</FormItem>
<FormItem>
{getFieldDecorator('isTrue', { rules: [{ required: true, message: 'Please Input Id!' }] })
(<CheckBox onChange={this.istrueChange} checked={this.state.istrue}/>)
}
</FormItem>
</Form>
</div>
)
}
}
const WrappedChild = Form.create()(Child);
export default WrappedChild;
2.父组件
class Father extends Component {
constructor() {
super()
this.state = {
"istrue": false
}
}
onClickHandler = (ref_id, e) => {
// 父组件的ref_id = 1赋值给state.ref_id
this.setState({ ref_id: ref_id })
this.setState({ visible: true })
}
onOkHandler = (e) => {
let child = this.refs.child
child.validateFields((err, values) => {
e.preventDefault();
// 刷新state.ref_id,也就刷新了ref_Form.props.id
this.setState({ ret_id: 2 });
// 通过
console.log(this.state.istrue);
// 父组件直接读写操作child.props.id是不允许的(可以理解为子组件的私有属性)
// 会报Cannot read property 'props' of undefined
child.props.id = 3
})
}
istrue = (istrue) => {
this.setState({ istrue: istrue })
}
render() {
<div>
<a href="javascript:;" onClick={e => this.onClickHandler(ref_id, e)} />
<Modal
title="请输入参数"
visible={this.state.visible}
onOk={this.onOkHandler}
onCancel={this.onCancelHandler}>
// 子组件通过props实现父组件将ref_id传递给子组件
// 子组件通过props实现子组件将istrue值传递给父组件,子组件中调用props.istrue实现了刷新父组件的state中istrue的值,这是一种行为参数化的思维,或者是回调函数的思维(在子组件中注册回调函数)
<WrappedChild ref="child" id={this.state.ref_id}
istrue={istrue => this.istrue(istrue)}/>
</Modal>
</div>
}
}
一些小TIPS
1.render()中报错:SyntaxError: Adjacent JSX elements must be wrapped in an enclosing tag
原因是render()函数中return的所有元素需要包裹在一个"根"元素里面,例如:
//错误代码:return了2个元素Form和Modal
render() {
const { getFieldDecorator } = this.props.form;
return (
<Form layout="vertical" onSubmit={this.onSubmit}>
......
</Form>
<Modal footer={null} visible={this.state.visible} title="result" onCancel={() => { this.setModalVisilble(false) }}>
......
</Modal>
);
}
// 正确代码,包了一层根元素:<div></div>
render() {
const { getFieldDecorator } = this.props.form;
return (
<div style={{ margin: 10 }}>
<Form layout="vertical" onSubmit={this.onSubmit}>
......
</Form>
<Modal footer={null} visible={this.state.visible} title="result" onCancel={() => { this.setModalVisilble(false) }}>
......
</Modal>
</div>
);
}
2.在父组件中不能通过ref访问子组件的props和state么,会直接报undefined错误