无状态组件(Stateless Component)
没有状态影响,就是纯静态展示作用。一般来说也是各UI库最先开发的组件类别,按钮,标签输入框等。他的基本组成是属性加一个渲染函数,由于不涉及状态更新,所以复用性也最强。
const PureComponent = (props) => (
<div>
//use props
</div>
)
没有生命周期方法,没有render方法,连state也没有,this也没有,也不需要实例化 。本质是一个带有返回值的函数,而且必须是使用闭合标签包裹的返回值。
有状态组件
如果组件内部包含状态(state)且状态随着事件或者外部的消息而发生改变的时候,这就构成了有状态组件(Stateful Component)。有状态组件通常会带有生命周期(lifecycle),用以在不同的时刻触发状态的更新。这种组件也是通常在写业务逻辑中最经常使用到的,根据不同的业务场景组件的状态数量以及生命周期机制也不尽相同。
class StatefulComponent extends Component {
constructor(props) {
super(props);
this.state = {
//定义状态
}
}
componentWillMount() {
//do something
}
componentDidMount() {
//do something
}
... //其他生命周期
render() {
return (
//render
);
}
}
容器组件
在具体的项目实践中,我们通常的前端数据都是通过Ajax请求获取的,而且获取的后端数据也需要进一步的做处理。为了使组件的职责更加单一,引入了容器组件(Container Component)的概念。我们将数据获取以及处理的逻辑放在容器组件中,使得组件的耦合性进一步地降低。
var UserListContainer = React.createClass({
getInitialState: function() {
return {
users: []
}
},
componentDidMount: function() {
var _this = this;
axios.get('/path/to/user-api').then(function(response) {
_this.setState({users: response.data});
});
},
render: function() {
return (<UserList users={this.state.users} />);
}
});
初始化state形式:
第一种,构造函数内定义,这是es6的实现
class AppComponent extends React.Component {
constructor(props){
super(props); // 调用父类的构造函数,改变this指向
this.state = {
loadding: false,
isshow: false,
data: null,
……
}
}
……
}
# 第二种,直接定义静态属性,这是es7的实现,更为简单,实用
class AppComponent extends React.Component {
state = {
loadding: false,
isshow: false,
data: null
……
}
……
}
props:
在调用时传入props
<div>
<AppComponent
data = {[]}
loadding = { true }
loadData = { 函数 }
/>
</div>
上面组件调用时传入了data, loadding, loadData三个props属性。这些传入的属性最终都会被收集到组件的props对象里面。
(stateless组件的props是通过传参传进去的,因为它本身是一个函数,没有this)
而获取props属性的方式也五花八门,下面直接看个粟子:
# 第一种,在内部展开获取
const AppComponent = (props) =>{
const { data, loadding, loadData } = props; // 通过es6的对象解构赋值的写法,直接从props获取到
/*
上面等同于:
const data = props.data;
const loadding = props.loadding;
const loadData = props.loadData;
*/
……
return <div>
这是一个干净纯洁的stateless组件
</div>
}
# 第二种,高逼格一些,直接从参数里解构出来,如下:
const AppComponent = ({ data, loadding, loadData }) =>{
……
return <div>
这是一个干净纯洁的stateless组件
</div>
}
或者,如果参数较多,可以写得优雅一些:
const AppComponent = ({
data,
loadding,
loadData
}) =>{
……
return <div>
这是一个干净纯洁的stateless组件
</div>
}
使用反向数据流来实现setState功能
(参照第一篇)
两个前提条件,一个是必须依赖一个父组件,二是这个父组件不是stateless组件,它有生命周期。
# 父组件
import ChildComponent from './ChildComponent'; // 引入子组件
class AppComponent extends React.Component {
state = {
msg:null,
content: null // 初始状态
}
changeLoad(content){ // 这个方法是传递给子组件调用的,并且子组件会传递content过来
this.setState({
msg: '反向传递成功',
content // { content } 等同于 { content: content }
})
}
render(){
return <div>
{ this.state.content }
<div>
<ChildComponent,
msg = { msg }
changeLoad = { this.changeLoad } // 调用子组件并传递msg以及changeLoad方法
/>
</div>
</div>
}
}
# 子组件
const ChildComponent =({ msg, changeLoad })=>{
const str = "我是一段文字,子组件把我这段文字传给了它的父组件,并在父组件中展示我";
return <div>
{ msg?msg:null }
<button onClick = { changeLoad(str) }> 点我传递str给父组件 </button> // 调用父组件的changeLoad方法并传递str给父组件
</div>
}