【推荐】react 最佳实践
2016-12-15 00:00
274 查看
摘要: 别人总结的react最佳实践,参考使用
帮助大家进一步了解React,帮助大家写出高效的可读性好的代码。
render 放在文件最后。因为我们经常打开一个React组件,优先寻找的方法就是
组件生命周期方法的生命周期执行顺序编写。便于理解以及问题的定位。
【正确】:
【错误】:
没有子节点的React组件,自闭合方式。
【推荐】
含有子节点的React组件
【推荐】
组件含有属性。
【推荐】
子组件的渲染条件根据props\state的数据
【推荐】:先声明-》根据条件处理子组件-》{ReactElement}
遍历数组常用方式。2种方式:map方法和forEach方法。
【Array.map方法】
如果想在this.setState之后立马获取新的state的值或者进行一些操作,可以在回调中执行
使用步骤:
在原生组件(HTML标签上)使用
通过
1、示例(原生组件-》HTML标签):
获取原生DOM节点之后,就可以使用它拥有的属性以及方法。
2、示例(自定义组件-》React组件):
【注意】:
由于
【推荐】:可以在
【错误使用】:在
被触发的条件:
父组件不用该子组件时候(null),子组件会被移除。子组件的生命周期方法
或者子组件父容器调用
子组件隐藏,或不可见时组件不卸载,
例如:
实现方式:
实现方式2, 在父组件中调用this.refs.xxx.setState();
【总结】:
方式1:父组件中,props发生变更的渠道只有一种方式的时候,推荐用这种方式。
方式2:父组件中,props发生变更的渠道存在多种方式的时候,推荐用这种方式。
JSX中的事件自动绑定、并且在组件卸载的时候,自动解除绑定。
扩展,暂时不需要掌握【ES6语法创建React组件】
JSX中的事件,需要手动绑定到当前组件的实例对象上,使得事件方法中的this指向的是该组件实例对象.
实践场景:
App中全局信息,组件嵌套层级很深,处于深处的子组件需要用到顶级的数据。若数据通过props方式一级一级往下传,很麻烦。可以通过此方式,让子组件访问到该数据
});
帮助大家进一步了解React,帮助大家写出高效的可读性好的代码。
React代码编写风格最佳实践
React组件内方法推荐的书写顺序。
/** * @fileoverview react组件内方法编写顺序 */ define(function(require, exports, module) { var ReactComponent = React.createClass({ propTypes: {}, contextTypes: {}, childContextTypes: {}, getDefaultProps: function() {}, getInitialState: function() {}, getChildContext: function() {}, // 组件生命周期方法 componentWillMount: function() {}, componentDidMount: function() {}, componentWillReceiveProps: function() {}, shouldComponentUpdate: function() {}, componentWillUpdate: function() {}, componentDidUpdate: function() {}, componentWillUnmount: function() {}, // 业务逻辑相关的处理方法 loadData: function() {}, parseData: function() {}, handleClick: function() {}, // 自动渲染虚拟DOM方法 render: function() {} }); module.exports = ReactComponent; });
render 放在文件最后。因为我们经常打开一个React组件,优先寻找的方法就是
render,放在底部容易寻找。
组件生命周期方法的生命周期执行顺序编写。便于理解以及问题的定位。
React组件JSX语法风格
render方法只能返回一个节点,如果想输出多个节点,必须使用一个根节点将它们包裹起来。【正确】:
return ( <div> <h2>title</h2> <div>content</div> </div> );
【错误】:
return ( <h2>title</h2> <div>content</div> );
没有子节点的React组件,自闭合方式。
【推荐】
return <ComponentView/>;【不推荐】
return <ComponentView></ComponentView>;
含有子节点的React组件
【推荐】
return ( <ComponentView> <ComponentChild/> </ComponentView> );
组件含有属性。
【推荐】
// 属性少,一行能放下放在一行 return <ComponentView className="list-wrap" rel="list"/>; // 属性多,>3个。多行显示。 return ( <ComponentView className="list-wrap" rel="list" onClick={this.handleClick} ... /> ); // 如果属性很多的话,推荐使用如下方式。把所有属性放在一个对象里面。 var props = { className: 'list-wrap', rel: 'list', onSuccess: this.onSuccess onError: this.onSuccess }; return <ComponentView {...props}/>;【不推荐】
return <ComponentView className="list-wrap" rel="list"/>;
子组件的渲染条件根据props\state的数据
【推荐】:先声明-》根据条件处理子组件-》{ReactElement}
module.exports = React.createClass({ getInitialState: function() { return { dataLoading: true }; }, render: function() { // 声明一个变量。 var loading; if (this.state.dataLoading) { loading = <Loading/>; } // 在JSX模板中,使用大括号{},引入子组件。 return ( <div> {loading} </div> ); } });
遍历数组常用方式。2种方式:map方法和forEach方法。
【Array.map方法】
var List = React.createClass({ getDefaultProps: function() { return { data: [{ name: 'test1' },{ name: 'test2' }] }; }, getInitialState: function() { return { data : this.props.data }; }, render: function(){ return ( <ul> { this.state.data.map(function(item, index){ return <li>{item.name}</li> }) } </ul> ); } });【Array.forEach方法】
var List = React.createClass({ getDefaultProps: function() { return { data: [{ name: 'test1' },{ name: 'test2' }] }; }, getInitialState: function() { return { data : this.props.data }; }, render: function(){ var items; this.state.data.forEach(function(item, index){ items.push(<li>{item.name}</li>); }) return ( <ul> {items} </ul> ); } });
如果想在this.setState之后立马获取新的state的值或者进行一些操作,可以在回调中执行
this.setState({ coin: 111 }, funtion(){ console.log(this.state); // 新的state对象 // 其他指定操作 }) console.log(this.state); // 旧的state对象
获取DOM节点
refs getDOMNode()
使用步骤:
在原生组件(HTML标签上)使用
ref="name"属性对一个 DOM节点进行标记
通过
this.refs.name.getDOMNode()获取到这个节点的原生 DOM。
1、示例(原生组件-》HTML标签):
获取原生DOM节点之后,就可以使用它拥有的属性以及方法。
<input ref="myInfo" data-id="xxx"/> var input = this.refs.myInfo.getDOMNode(); // 获取value var inputValue = input.value; // 自定义属性 var inputAttr = input.getAttributes('data-id'); // 失去焦点 input.blur(); // 获得焦点 input.focus();
2、示例(自定义组件-》React组件):
<List ref="list" data={data} /> var list = this.refs.list.getDOMNode(); // 修改子组件实例的状态,触发render list.setState({ data: newData }); // 可以使用子组件实例中的方法 ...
【注意】:
由于
this.refs.name.getDOMNode()获取到是真实的DOM,必须等虚拟DOM节点插入文档中后,才能用到这个属性,否则就会报错。
【推荐】:可以在
componentDidMount方法中调用、存储DOM节点。
【错误使用】:在
render方法中访问
refs属性。报错!!
componentWillUnmount
使用场景:移除组件前,这里可以做一些清除工作,例如清除内存,解除事件的监听等等。被触发的条件:
父组件不用该子组件时候(null),子组件会被移除。子组件的生命周期方法
componentWillUnmount会被触发。
或者子组件父容器调用
ReactDOM.unmountComponentAtNode(container)。container中的所有组件都会被卸载,所有子组件的
componentWillUnmount方法都会触发。
子组件隐藏,或不可见时组件不卸载,
componentWillUnmount方法不会触发的
例如:
var Loading = React.createClass({ getDefaultProps: function(){ return { text: '加载中' }; }, componentWillUnmount: function(){ console.log('componentWillUnmount'); }, render: function(){ return ( <div className="loading">{this.props.text}</div> ); } }); module.exports = React.createClass({ getInitialState: function() { return { dataLoading: true }; }, render: function() { var loading = null; if (this.state.dataLoading) { loading = <Loading/> } return ( <div> {loading} </div> ); } }); // 当this.state.dataLoading = false时候,<Loading/>被卸载。<Loading/>组件中的componentWillUnmount在组件卸载前会被触发。
数据
通过AJAX加载初始数据
【推荐】在componentDidMount方法中异步加载初始数据。
var AjaxC = React.createClass({ componentDidMount: function(){ var self = this; var promise = $.ajax({ url:'', type: 'GET' data: '' }); promise.done(function(res){ if(res.errcode == 0) { // 请求成功,更新state,触发render方法更新视图UI self.setState({ data: res.data }) } }); }, render: function(){ //.... } });
子组件数据依赖父组件,在父组件中,数据方法变更,要求子组件UI一起更新
子组件的数据由父组件提供,父组件通过props将数据传给子组件。组件嵌套结构 - ParentComponent - ChildComponent
实现方式:
componentWillReceiveProps
var ParentComponent = React.createClass({ componentDidMount: function(){ var self = this; var promise = $.ajax({ url:'', type: 'GET' data: '' }); promise.done(function(res){ if(res.errcode == 0) { // 请求成功,更新state,触发render方法更新视图UI self.setState({ avatar: res.data }) } }); }, render: function(){ return ( <div> <div> 图片地址: {this.state.avatar} </div> <ChildComponent avatar={this.state.avatar} ref="child"/> </div> ); } }); var ChildComponent = React.createClass({ getInitialState: function() { return this.copyPropsToState(this.props); }, /** * 单独一个方法。组件状态处理,依赖props */ copyPropsToState: function(props) { return { avatar: props.avatar } }, componentWillReceiveProps: function(nextProps) { this.setState(this.copyPropsToState(nextProps)); }, render: function(){ return ( <img ref="avatar" src={this.state.avatar}/> ); } });
实现方式2, 在父组件中调用this.refs.xxx.setState();
var ParentComponent = React.createClass({ componentDidMount: function(){ var self = this; var promise = $.ajax({ url:'', type: 'GET' data: '' }); promise.done(function(res){ if(res.errcode == 0) { // 请求成功,更新state,触发render方法更新视图UI self.setState({ avatar: res.data }) self.refs.child.setState({ avatar: res.data }) } }); }, render: function(){ return ( <div> <div> 图片地址: {this.state.avatar} </div> <ChildComponent avatar={this.state.avatar} ref="child"/> </div> ); } }); var ChildComponent = React.createClass({ getInitialState: function() { return { avatar: this.props.avatar || "" } }, render: function(){ return ( <img ref="avatar" src={this.state.avatar}/> ); } });
【总结】:
方式1:父组件中,props发生变更的渠道只有一种方式的时候,推荐用这种方式。
方式2:父组件中,props发生变更的渠道存在多种方式的时候,推荐用这种方式。
事件绑定
在JSX中使用事件
使用React.createClass() 创建React组件:JSX中的事件自动绑定、并且在组件卸载的时候,自动解除绑定。
React.createClass({ render: function(){ return ( <input type="text" onClick={this.handleClick}/> ); }, handleClick: function(e){ // this为当前组件实例对象。 this.setStata({ data: '11' }) } }); // 若事件需要传参数 React.createClass({ render: function(){ return ( <input type="text" onClick={this.handleClick.bind(this, '传的参数')}> ); }, /** * @param data 传的参数 * @param e event对象 */ handleClick: function(data, e){ console.log(data) // => "传的参数" // 获取发生点击事件的DOM节点,使用方式同以前。 var target = e.currentTarget; // this为当前组件实例对象。 this.setStata({ data: '11' }) } });
扩展,暂时不需要掌握【ES6语法创建React组件】
JSX中的事件,需要手动绑定到当前组件的实例对象上,使得事件方法中的this指向的是该组件实例对象.
<input type="text" onClick={this.handleClick.bind(this)}/>
其他普通事件绑定
【推荐】:在componentDidMount方法中绑定普通的DOM事件,并且在
componentWillUnmount中移除这些事件
var Scroll = React.createClass({ componentDidMount: function(){ // 请求数据 this.loadData(); // 绑定事件 this.bindEvent(); }, componentWillUnmount: function(){ console.log('off scroll event'); $(window).off('scroll'); }, loadData: function(){ //... }, bindEvent: function(){ console.log('bind scroll event'); $(window).on('scroll', function() { // 事件滚动操作 }); }, render: function(){ } });
Context
https://facebook.github.io/react/docs/context-zh-CN.html实践场景:
App中全局信息,组件嵌套层级很深,处于深处的子组件需要用到顶级的数据。若数据通过props方式一级一级往下传,很麻烦。可以通过此方式,让子组件访问到该数据
// 1. 在上级组件中,通过childContextTypes属性和getChildContext方法,定义组件可访问的数据(还可以是方法)。 var Parent = React.createClass({ childContextTypes: { goldCoin: React.PropTypes.any, getColdCoin: React.PropTypes.any, updateGoldCoin:React.PropTypes.any, }, getChildContext: function(){ return { goldCoin: this.state.goldCoin, // 第一次渲染组件时,就固定了子组件获取的值。 getGoldCoin: this.getGoldCoin, // 如果n数据是变更的,推荐使用方法去获取 updateGoldCoin: this.updateGoldCoin } }, updateGoldCoin: function(goldCoin){ this.setState({ goldCoin: goldCoin }); }, getGoldCoin: function(){ return Number(this.state.goldCoin); } }) // 2. 子组件中,可以通过this.context.xxx访问上级顶级的数据或者方法 var Child = React.createClass({ contextTypes: { goldCoin: React.PropTypes.any, getColdCoin: React.PropTypes.any, updateGoldCoin: React.PropTypes.any }, ... render: function(){ ... }, ... updateGoldCoin: function(){ var goldCoin = this.context.getGoldCoin(); var newGoldCoin = '333333'; this.context.updateGoldCoin(newGoldCoin); }
});
相关文章推荐
- CentOS 6.X设置环境时间最佳实践 推荐
- React Native 如何设计登录模块?有何最佳实践?
- 转:OpenResty最佳实践(推荐了解lua语法)
- 强烈推荐C++编程规范:101条规则、准则与最佳实践
- 将React组件迁移到ES6最佳实践
- React 最佳实践——那些 React 没告诉你但很重要的事
- 微服务架构的两大解耦利器与最佳实践 推荐
- XenServer虚拟机最佳实践 推荐
- [推荐]Rolling cURL: PHP并发最佳实践 商品价格监控 curl_multi族 函数
- React最佳实践
- 推荐:《中文排版的最佳实践》 _使得长篇文章更易读的十条法则(转)
- Provisioning Services最佳实践一 ----概括 推荐
- javascript编程的最佳实践推荐
- 组策略最佳实践之“降龙十八掌” 推荐
- 新书推荐:《Liferay Portal 6.1门户网站建设最佳实践》
- openstack 扩展开发最佳实践之计算节点高可用 推荐
- 蛙蛙推荐:Backbone和seajs搭配最佳实践探讨
- React 最佳实践——那些 React 没告诉你但很重要的事
- 敏捷开发方法Scrum最佳实践 推荐