react五种组件形式

127 阅读3分钟

无状态组件(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>
}