总结React组件的三种写法及最佳实践
React 专注于 view 层,组件化则是 React 的基础,也是其核⼼理念之⼀,⼀个完整的应⽤将由⼀个个独⽴的组件拼装⽽成。
截⾄⽬前 React 已经更新到 v15.4.2,由于 ES6 的普及和不同业务场景的影响,我们会发现⽬前主要有三种创建 React 组件的写法:1. ES5写法ateClass,2. ES6写法React.Component,3. ⽆状态的函数式写法(纯组件-SFC)。
你们最钟爱哪种写法呢?萝⼘青菜各有所爱~ 每个团队都有⾃⼰的代码规范和开发模式,但书写 React 组件时都会以提⾼代码阅读性、更优的组件性能、易于 bug 追踪为原则。下⾯我们就聊聊这三种写法的区别,以及各⾃所适⽤场景的最佳实践。
ES5-写法 ateClass
法,render返回⼀个组件实例,下⾯⽤⼀个 SwitchButton 组件的例⼦来看看ateClass的具体⽤法:
1 var React = require('react');
2 var ReactDOM = require('react-dom');
3
4 var SwitchButton = ateClass({
5 getDefaultProp:function() {
6 return { open: false }
7 },
8
9 getInitialState: function() {
10 return { open: this.props.open };
11 },
12
13 handleClick: function(event) {
14 this.setState({ open: !this.state.open });
15 },
16
17 render: function() {
18 var open = this.state.open,
19 className = open ? 'switch-button open' : 'btn-switch';
20
21 return (
22 <label className={className} onClick={this.handleClick.bind(this)}>
23 <input type="checkbox" checked={open}/>
24 </label>
25 );
26 }
27 });
28
der(
30 <SwitchButton />,
31 ElementById('app')
32 );
ES6-写法 React.Component
React 升级到 v0.13 后就⽀持了 ES6 的class语法,我们可以使⽤class App extends React.Component{...}的⽅式创建组件,这也是⽬前官⽅推荐创建有状态组件的⽅式。⽤ ES6 重写上⾯ SwitchButton 组件的例⼦:
1 import React from 'react'
2 import { render } from 'react-dom'
3
4 class SwitchButton extends React.Component {
5 constructor(props) {
6 super(props)
7 this.state = {
8 open: this.props.open
9 }
10 this.handleClick = this.handleClick.bind(this)
11 }
12
13 handleClick(event) {
14 this.setState({ open: !this.state.open })
15 }
16
17 render() {
18 let open = this.state.open,
19 className = open ? 'switch-button open' : 'btn-switch'
20
21 return (
22 <label className={className} onClick={this.handleClick}>
23 <input type="checkbox" checked={open}/>
24 </label>
25 )
26 }
27 }
28
29 SwitchButton.defaultProps = {
30 open: false
31 }
32
33 render(
34 <SwitchButton />,
35 ElementById('app')
36 )
与ateClass创建组件的不同之处:
import
与这⾥使⽤了 ES6 的import语句替代require()⽅法导⼊模块,其中import {render}可以直接从模块中导⼊变量名,这种写法更加简洁直观。
react面试题ref概念初始化 state
React 使⽤ ES6 的“类”继承实现时,去掉了getInitialState这个 hook 函数,state的初始化放在构造函数⽅法constructor中声明。
this 绑定
React.Component创建组件时,事件函数并不会⾃动绑定this,需要我们⼿动绑定,不然this将不会指向当前组件的实例对象。以下有三种绑定this的⽅法:
1. 在constructor中使⽤bind()进⾏硬绑定
constructor() {
this.handleClick = this.handleClick.bind(this);
}
2. 直接在元素上使⽤bind()绑定
<label className={className} onClick={this.handleClick.bind(this)}>
3. ES6 有个很有⽤的语法糖:Arrow Function(箭头函数)它可以很⽅便的使this直接指向class SwitchButton(它的作⽤等同于⼤家熟悉的var self = this,但后者会让代码变得混乱,Arrow Function 就很好的解决了这⼀问题)
<label className={className} onClick={()=>this.handleClick()}>
⽆状态的函数式写法(纯组件 SFC)
它的出现是因为随着应⽤复杂度不断提升和组件本数量的增加,组件按各⾃职责被分成不同的类型,于是有⼀种只负责展⽰的纯组件出现了,它的特点是不需要管理状态state,数据直接通过props传⼊,这也符合 React 单向数据流的思想。
对于这种⽆状态的组件,使⽤函数式的⽅式声明,会使得代码的可读性更好,并能⼤⼤减少代码量,Arrow Function 则是函数式写法的最佳搭档:
1 const Todo = (props) => (
2 <li
3 onClick={Click}
4 style={{textDecoration: propsplete ? "line-through" : "none"}}
5 >
6 {}
7 </li>
8 )
上⾯定义的 Todo 组件,输⼊输出数据完全由props决定,⽽且不会产⽣任何副作⽤。对于props为 Object 类型时,我们还可以使⽤ ES6 的解构赋值:
1 const Todo = ({ onClick, complete, text, ...props }) => (
2 <li
3 onClick={onClick}
4 style={{textDecoration: complete ? "line-through" : "none"}}
5 {...props}
6 >
7 {}
8 </li>
9 )
⽆状态组件⼀般会搭配⾼阶组件(简称:OHC)⼀起使⽤,⾼阶组件⽤来托管state,Redux 框架就是通过 store 管理数据源和所有状态,其中所有负责展⽰的组件都使⽤⽆状态函数式的写法。
这种模式被⿎励在⼤型项⽬中尽可能以简单的写法来分割原本庞⼤的组件,⽽未来 React 也会⾯向这种⽆状态的组件进⾏⼀些专门的优化,⽐如避免⽆意义的检查或内存分配。所以建议⼤家尽可能在项⽬中使⽤⽆状态组件。
当然,⽆状态组件也不是万⾦油,⽐如它不⽀持"ref",原因很简单,因为 React 调⽤它之前,组件不会被实例化,⾃然也就没有"ref",(ref 和findDOMNode实际上打破了⽗⼦组件之间仅通过 props 来传递状态的约定,违背了 React 的原则,需要避免)。
以上三种写法的⽐较,以及最佳实践
Facebook 官⽅早就声明 ES6React.Component将取代ateClass。随着 React 不断发展,Rea
总的来说:⽆状态函数式写法优于ateClass,⽽ateClass优于React.Component。
参考资料:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论