React 16.8中正式发布了React Hooks,主要是想解决如何复用一个有状态的组件的问题。实际上React Hooks就是一系列特殊的函数,可以让本来无状态的函数组件变成有状态的,在组件内部hook组件的状态state和lifecycle。不过在正式总结React Hooks前,有必要搞清楚一些比较基本的问题,例如:什么是组件,什么是有状态组件和无状态组件,它们各自有什么特点,如何创建组件。本文根据这一思路将梳理关于React组件的基本内容,具体包括:
React的一个核心思想就是把页面拆分成一个个独立、可重用的组件,并且用自上而下的单向数据流将这些组件串联起来,在React中是这样定义组件的:
Components let you split the UI into independent, reusable pieces, and think about each piece in isolation.
就是说通过使用组件 可以把页面拆分为独立的、可重用的部分,并可以单独地考虑每个部分。
另外注意在React中组件名称必须以大写字母开头,React 会将以小写字母开头的组件视为原生 DOM 标签。例如,<div /> 代表 HTML 的 div 标签,而 <Welcome /> 则代表一个组件,并且需在作用域内使用 Welcome。
React定义React组件的方式:
(1)出现版本:从React 0.14开始出现,可点击
(2)组件形式:函数组件是无状态的组件,只根据传入的属性props做展示、带有render方法。没有state状态的操作、没有生命周期lifecycle,可通过函数形式或者ES6的箭头函数创建。
// 1,函数组件
function Welcome(props) {
return <h1>Hello, {props.name}</h1>
}
ReactDOM.render(<Welcome name="Peter" />, document.getElementById('root'))
(3)函数组件的特点:
总的来说,React的建议是
This pattern is designed to encourage the creation of these simple components that should comprise large portions of your apps.
只要有可能,尽量使用无状态组件。
提前说明:如果想创建一个类组件,请使用ES6的React.Component的形式来创建。
(1)说明:这是React刚开始推荐的创建组件的方式。是ES5的原生的JavaScript来实现的React组件。再次强调,React更推荐用React.Component的方式去创建有状态的组件。
(2)组件形式:类组件是有状态的组件,自然组件要被实例化,且可以访问state、lifecycle。
示例:
// 2,React.createClass
import React from 'react'
import ReactDOM from 'react-dom'
const SwitchButton = React.createClass({
getDefaultProp: function () {
return {
open: false
}
},
// 返回初始的state
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' : 'switch-button';
return (
<label
className={className}
onClick={this.handleClick}>
<input type="checkbox" checked={open} />开
</label>);
}
});
ReactDOM.render(<SwitchButton />, document.getElementById('root'));
(3)React.createClass的特点:
(1)说明:是以ES6的方式来创建React组件
(2)组件形式
示例,上述代码用ES6的React.Component实现:
// 3,React.Component
import React from 'react'
import ReactDOM from 'react-dom'
class SwitchButton extends React.Component {
constructor(props) {
super(props)
// 返回初始的state,相当于ES5中的getInitailState
this.state = {
open: this.props.open
}
// 这句要注意,React.component中函数不会自动绑定this,要手动绑定
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' : 'switch-btn'
return (
<label
className={className}
onClick={this.handleClick}>
<input type="checkbox" checked={open} /> 开
</label>)
}
}
// 相当于React.createClass中的getDefaultProps
SwitchButton.defaultProps = {
open: false
}
ReactDOM.render(<SwitchButton />, document.getElementById('root'))
需要注意,React.component中函数不会自动绑定this,要手动绑定。有三种手动绑定的方式:
-- 在构造函数中绑定,就是上述示例中采用的方法:
constructor(props) {
super(props)
this.state = {
...
}
this.handleClick = this.handleClick.bind(this)
}
-- 在调用时绑定:
onClick={this.handleClick.bind(this)}
-- 使用ES6的箭头函数来绑定:
onClick={()=>this.handleClick()}
(3)React.Component的特点:
The most notable new feature is support for ES6 classes , which allows developers to have more flexibility when writing components. Our eventual goal is for ES6 classes to replace React.createClass completely, but until we have a replacement for current mixin use cases and support for class property initializers in the language, we don’t plan to deprecate React.createClass.
可以看出React更推荐以React.Component的形式来创建一个有状态的组件,React.Component最终会完全取代React.createClass。但在找到Mixins的替代方案前,不会废弃掉React.createClass。不过9102年了,在HOC、Render Props、React Hooks这些解决方案都出现的今天,Mixins已被开发团队坚决地舍弃了。总的来说,现在要创建一个有状态的组件,请用React.Component的形式来创建。
1,尽可能使用函数组件创建;
2,除非需要state、lifecycle等,使用React.Component这种ES6的形式创建有状态的类组件;
3,如果想在函数组件中使用state、lifecycle,使用React Hooks;
上面已经说过,函数组件是无状态的组件,类组件是有状态的组件。
React中有五类API:
有状态的组件:组件内部可以使用状态(state)、生命周期(lifecycle)、render
无状态的组件:组件内部可以使用属性(props)、context、render。
更多关于React组件模式的内容,可以阅读 React组件模式
所谓受控组件、非受控组件,都是针对form表单而言的。
受控组件就是表单元素有当前值(value),同时还有一个回调函数(onChange)可以改变这个值,回调函数中通过使用setState()更新对应的state值,示例:
// 受控组件
import React from 'react'
class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
};
}
handleNameChange = (event) => {
// 在回调函数中用event.target.value获取新的值
this.setState({
name: event.target.value
});
};
render() {
return (
<div>
<input
type="text"
value={this.state.name}
onChange={this.handleNameChange}
/>
</div>
);
}
}
非受控组件是不受状态的控制,可以使用defaultValue、defaultChecked设置初始值,使用ref来获取DOM的值。
<input
type="text"
defualtValue="Peter"
ref={input => this._name = input}
/>
形式上,如果是通过value属性、checked属性来设置表单元素的值,那么表单元素就是受控的。如图,右边是受控的:
万丈高楼平地起,作为介绍React Hooks的基础篇,本文主要梳理了什么是组件、三种创建组件的方式,各自的特点,以及如何进行选择。接下来总结了什么是有状态组件、无状态组件、受控组件和非受控组件。如有问题,欢迎指正。
[1]http://www.cnblogs.com/wonyun/p/5930333.html
[2]https://medium.com/teamsubchannel/react-component-patterns-e7fb75be7bb0
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。