React学习:组件的分类

React 组件有很多种分类方式,常见的分类方式有函数组件和类组件,无状态组件和有状态组件,展示型组件和容器型组件。真正理解它们还是对开发有很大益处的。


1、 函数组件和类组件

划分依据是根据组件的定义方式。

例:下面的两种写法等价

//函数式组件
function MyComponent(props){
    return <h1>Hello,{props.name}</h1>;
}

//类组件
class MyComponent extends React.Component{
    render(){
        return <h1>Hello,{this.props.name}</h1>;
    }
}
  • 类组件:比函数组件功能更加强大。类组件可以维护自身的状态变量state,类组件还有不同的生命周期方法,可以让开发者能够在组件的不同阶段(挂载、更新、卸载),对组件做更多的控制。
  • 函数组件:更加专注和单一,它只关注对应UI的展现,返回React 元素。

实际操作上,当一个组件不需要管理自身状态时,可以把它设计成函数组件,当你有足够的理由发现它需要“升级”为类组件时,再把它改造为类组件。因为函数组件“升级”为类组件是有一定成本的,这样就会要求你做这个改造前更认真地思考其合理性,而不是仅仅为了一时的方便就使用类组件。


2、 无状态组件和有状态组件

划分依据是根据组件内部是否有state。无状态组件内部不使用state,只根据外部组件传入的props返回待渲染的React 元素。有状态组件内部使用state,维护自身状态的变化,有状态组件根据外部组件传入的props和自身的state,共同决定最终返回的React 元素。

函数组件一定是无状态组件,类组件则既可以充当无状态组件,也可以充当有状态组件。


3、 展示型组件和容器型组件

划分依据是根据组件的职责。
简单说:展示型组件主要负责UI展示;容器型组件主要负责逻辑数据处理。

展示型组件的职责是:组件UI长成什么样。展示型组件不关心组件使用的数据是如何获取的,以及组件数据应该如何修改,它只需要知道有了这些数据后,组件UI是什么样子的即可。外部组件通过props传递给展示型组件所需的数据和修改这些数据的回调函数,展示型组件只是它们的使用者。展示型组件一般是无状态组件,不需要state,因为展示型组件不需要管理数据,但当展示型组件需要管理自身的UI状态时,例如控制组件内部弹框的显示与隐藏,是可以使用state的,这时的state属于UI state。既然大部分情况下展示型组件不需要state,应该优先考虑使用函数组件实现展示型组件。

容器型组件的职责是:组件数据如何工作。容器型组件需要知道如何获取子组件所需数据,以及这些数据的处理逻辑,并把数据和逻辑通过props提供给子组件使用。容器型组件一般是有状态组件,因为它们需要管理页面所需数据。

例如,下面的例子中,UserListContainer是一个容器型组件,它获取用户列表数据,然后把用户列表数据传递给展示型组件UserList,由UserList负责UI的展现。

//容器型组件
class UserListContainer extends React.Component{
  constructor(props){
    super(props);
    this.state = {
      users: []
    }
  }
  componentDidMount() {
    var that = this;
    fetch('/path/to/user-api').then(function(response) {
      response.json().then(function(data) {
        that.setState({users: data})
      });
    });
  }
  render() {
    return (
      <UserList users={this.state.users} />
    )
  }
}

//展示型组件
function UserList(props) {
  return (
    <div>
      <ul className="user-list">
        {props.users.map(function(user) {
          return (
            <li key={user.id}>
              <span>{user.name}</span>
            </li>
          );
        })}
      </ul>
    </div>
  )  
}

展示型组件和容器型组件是可以互相嵌套的,展示型组件的子组件既可以包含展示型组件,也可以包含容器型组件,容器型组件也是如此。例如,当一个容器型组件承担的数据管理工作过于复杂时,可以在它的子组件中定义新的容器型组件,由新组件分担数据的管理。

扫描二维码关注公众号,回复: 2590376 查看本文章

4、 受控组件和非受控组件

(1)受控组件:之前说过不解释。 (点我点我)
(2)非受控组件:下面主要讲解

非受控组件

在大多数情况下,我们推荐使用受控组件来实现表单。在受控组件中,表单数据由 React 组件负责处理。另外一个选择是不受控组件,其表单数据由 DOM 元素本身处理。
要编写一个未控制组件,你可以使用一个 ref 来从 DOM 获得 表单值,而不是为每个状态更新编写一个事件处理程序。

例:

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.input.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" ref={(input) => this.input = input} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

因为不受控组件的数据来源是 DOM 元素,当使用不受控组件时很容易实现 React 代码与非 React 代码的集成。如果你希望的是快速开发、不要求代码质量,不受控组件可以一定程度上减少代码量。否则。你应该使用受控组件。

非受控组件的默认值

在 React 渲染生命周期中,表单元素中的 value 属性将会覆盖 DOM 中的 value 。在不受控组件中,你可能希望 React 有初始值,但保留后续更新不受控制。在这种情况下,你需要使用 defaultValue 属性而不是 value 属性。

render() {
  return (
    <form onSubmit={this.handleSubmit}>
      <label>
        Name:
        <input
          defaultValue="Bob"
          type="text"
          ref={(input) => this.input = input} />
      </label>
      <input type="submit" value="Submit" />
    </form>
  );
}

同样, <input type="checkbox"><input type="radio"> 支持 defaultChecked,而 <select><textarea> 支持 defaultValue。

猜你喜欢

转载自blog.csdn.net/b954960630/article/details/80198894
今日推荐