特别声明:如果您喜欢小站的内容,可以点击申请会员进行全站阅读。如果您对付费阅读有任何建议或想法,欢迎发送邮件至: airenliao@gmail.com!或添加QQ:874472854(^_^)
组件的概念在Web中应用的场景已经相当广泛了。而React是专注于View层的,组件也是React核心理念之一,一个完整的应用将由一个个独立的组件拼装而成。组件也是React最基础的一部分,欲想征服React,那么了解和编写组件就显得尤为重要。
在上一篇文章,咱们就写了一个最简单的React组件,而且在文章末尾,咱们留了一个问题,怎么创建无状态和有状态的React组件?接下来,就一起来了解React中的无状态和有状态的组件。
React中创建组件的方式
在了解React中的无状态和有状态的组件之前,先来了解在React中创建组件的姿势。简单的说,在React中创建组件有三种方式:
- ES5写法:
React.createClass
- ES6写法:
React.Component
- 无状态的函数写法,又称为纯组件SFC
React.createClass
React.createClass
是React刚开始推荐的创建组件的方式。这是ES5的原生的JavaScript来实现的React组件。React.createClass
这个方法构建一个组件“类”,它接受一个对象为参数,对象中必须声明一个render()
方法,render()
方法将返回一个组件实例。
先来看一个React.createClass
创建组件的形式:
import React from 'react'
import ReactDOM from 'react-dom'
const SwitchButton = React.createClass({
getDefaultProp:function() {
return { open: false }
},
getInitialState: function() {
return { open: this.props.open };
},
handleClick: function(event) {
this.setState({ open: !this.state.open });
},
render: function() {
var open = this.state.open,
className = open ? 'switch-button open' : 'btn-switch';
return (
<label className={className} onClick={this.handleClick.bind(this)}>
<input type="checkbox" checked={open}/>男
</label>
);
}
});
ReactDOM.render(
<SwitchButton />,
document.getElementById('root')
);
React.createClass
是用来创建有状态的组件,这些组件是要被实例化的,并且可以访问组件的生命周期方法。不过React.createClass
创建React组件有其自身的问题存在:
React.createClass
会自动绑定函数方法,导致不必要的性能开销,增加代发过时的可能性React.createClass
的mixins
不够自然、直观
React.Component
React.Component
是以ES6的形式来创建React组件,也是现在React官方推荐的创建组件的方式,其和React.createClass
创建的组件一样,也是创建有状态的组件。而且React.Component
最终会取代React.createClass
。
把上面的例子,用React.Component
来修改:
import React from 'react'
import ReactDOM from 'react-dom'
class SwitchButton extends React.Component {
constructor(props) {
super(props)
this.state = {
open: this.props.open
}
this.handleClick = this.handleClick.bind(this)
}
handleClick(event) {
this.setState({ open: !this.state.open })
}
render() {
let open = this.state.open,
className = open ? 'switch-button open' : 'btn-switch'
return (
<label className={className} onClick={this.handleClick}>
<input type="checkbox" checked={open}/> 男
</label>
)
}
}
SwitchButton.defaultProps = {
open: false
}
ReactDOM.render(
<SwitchButton />,
document.getElementById('root')
)
React.Component
和React.createClass
创建组件有蛮多不同之处,有关于这两者的区别,@toddmotto去年就写过一篇《React.createClass
versus extends React.Component
》,文章对两者之间做过详细的阐述。
无状态的函数写法
无状态的函数创建的组件是无状态组件,它是一种只负责展示的纯组件:
function HelloComponent(props) {
return <div>Hello {props.name}</div>
}
ReactDOM.render(<HelloComponent name="marlon" />, mountNode)
对于这种无状态的组件,使用函数式的方式声明,会使得代码的可读性更好,并能大大减少代码量,箭头函数则是函数式写法的最佳搭档:
const Todo = (props) => (
<li
onClick={props.onClick}
style={{textDecoration: props.complete ? "line-through" : "none"}}
>
{props.text}
</li>
)
上面定义的 Todo
组件,输入输出数据完全由props
决定,而且不会产生任何副作用。对于props
为 Object
类型时,我们还可以使用 ES6 的解构赋值:
const Todo = ({ onClick, complete, text, ...props }) => (
<li
onClick={onClick}
style={{textDecoration: complete ? "line-through" : "none"}}
{...props}
>
{props.text}
</li>
)
无状态组件一般会搭配高阶组件(简称:HOC)一起使用,高阶组件用来托管state
,Redux 框架就是通过 store
管理数据源和所有状态,其中所有负责展示的组件都使用无状态函数式的写法。
这种模式被鼓励在大型项目中尽可能以简单的写法 来分割原本庞大的组件,而未来 React 也会面向这种无状态的组件进行一些专门的优化,比如避免无意义的检查或内存分配。所以建议大家尽可能在项目中使用无状态组件。
无状态组件内部其实是可以使用ref
功能的,虽然不能通过this.refs
访问到,但是可以通过将ref
内容保存到无状态组件内部的一个本地变量中获取到。
例如下面这段代码可以使用ref
来获取组件挂载到DOM中后所指向的DOM元素:
function TestComp(props){
let ref;
return (
<div ref={(node) => ref = node}></div>
)
}
如何选择创建组件的方式
Facebook 官方早就声明 ES6 React.Component
将取代React.createClass
如需转载,烦请注明出处:https://www.w3cplus.com/react/stateful-vs-stateless-components.html
如果文章中有不对之处,烦请各位大神拍正。如果你觉得这篇文章对你有所帮助,打个赏,让我有更大的动力去创作。(^_^)。看完了?还不过瘾?点击向作者提问!