返回介绍

四、组件类型

发布于 2024-09-07 17:54:33 字数 5136 浏览 0 评论 0 收藏 0

4.1 函数定义与类定义组件

第一种函数定义组件,非常简单啦,我们只需要定义一个接收 props 传值,返回 React 元素的方法即可

function Title(props) {
  return <h1>Hello, {props.name}</h1>
}
// 甚至使用 ES6 的箭头函数简写之后可以变成这样
const Title = props => <h1>Hello, {props.name}</h1>

第二种是类定义组件,也就是使用 ES6 中新引入的类的概念来定义 React 组件

  • 组件在定义好之后,可以通过 JSX 描述的方式被引用,组件之间也可以相互嵌套和组合
class Title extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>
  }
}

4.2 展示与容器组件

// 展示组件

class CommentList extends React.Component {
  constructor(props) {
    super(props)
  }

  renderComment({body, author}) {
    return <li>{body}—{author}</li>
  }
  
  render() { 
    return <ul> {this.props.comments.map(this.renderComment)} </ul>
  } 
  
}
// 容器组件
class CommentListContainer extends React.Component {
  constructor() {
    super()
    this.state = { comments: [] }
  }
  
  componentDidMount() {
    $.ajax({
      url: "/my-comments.json",
      dataType: 'json',
      success: function(comments) {
        this.setState({comments: comments})
      }.bind(this)
    })
  }
  
  render() {
    return <CommentList comments={this.state.comments} />
  }
}

展示组件

  • 主要负责组件内容如何展示
  • props 接收父组件传递来的数据
  • 大多数情况可以通过函数定义组件声明

容器组件

  • 主要关注组件数据如何交互
  • 拥有自身的 state ,从服务器获取数据,或与 redux 等其他数据处理模块协作
  • 需要通过类定义组件声明,并包含生命周期函数和其他附加方法

那么这样写具体有什么好处呢?

  • 解耦了界面和数据的逻辑
  • 更好的可复用性,比如同一个回复列表展示组件可以套用不同数据源的容器组件
  • 利于团队协作,一个人负责界面结构,一个人负责数据交互

4.3 有状态与无状态组件

有状态组件

这个组件能够获取储存改变应用或组件本身的状态数据,在 React 当中也就是 state ,一些比较明显的特征是我们可以在这样的组件当中看到对 this.state 的初始化,或 this.setState 方法的调用

无状态组件

这样的组件一般只接收来自其他组件的数据。一般这样的组件中只能看到对 this.props 的调用

// 有状态组件
class StatefulLink extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      active: false
    }
  }
  handleClick() {
    this.setState({
      active: !this.state.active
    })
  }
  render() {
    return <a 
          style={{ color: this.state.active ? 'red' : 'black' }}
          onClick={this.handleClick.bind(this)}
         >
           Stateful Link
         </a>
  }
}
// 无状态组件
class StatelessLink extends React.Component {
  constructor(props) {
    super(props)
  }
  handleClick() {
    this.props.handleClick(this.props.router)
  }
  render() {
    const active = this.props.activeRouter === this.props.router
    return (
        <li>
            <a 
              style={{ color: active ? 'red' : 'black' }}
              onClick={this.handleClick.bind(this)}
             >
                Stateless Link
            </a>
    </li>
    )
  }
}

React 的实际开发当中,我们编写的组件大部分都是无状态组件。毕竟 React 的主要作用是编写用户界面。再加上 ES6 的新特性,绝大多数的无状态组件都可以通过箭头函数简写成类似下面这样

const SimpleButton = props => <button>{props.text}</button>

4.4 受控与非受控组件

受控组件

比如说设置了 value<input> 是一个受控组件。对于受控的 <input> ,渲染出来的 html 元素始终保持着 value 属性的值,如以下代码

  • 此时如果想要更新用户的值。需要使用 onChange 事件

非受控组件

即没有设置 value 或者设置为 null 的是一个非受控组件,对于非受控的 input 组件,用户的输入会直接反映在页面上

  • 上面的代码渲染出一个空值的输入框,用户的输入立即会反映在元素上
  • 和受控组件一样,使用 onChange 事件来监听值的变化,如果想要给组件设置一个非空的初始值。可以使用 defaultValue
  • 通常情况下, React 当中所有的表单控件都需要是受控组件

4.5 组合与继承

  • React 当中的组件是通过嵌套或组合的方式实现组件代码复用的
  • 通过 props 传值和组合使用组件几乎可以满足所有场景下的需求。这样也更符合组件化的理念,就好像使用互相嵌套的 DOM 元素一样使用 React 的组件,并不需要引入继承的概念

继承的写法并不符合 React 的理念。在 React 当中 props 其实是非常强大的, props 几乎可以传入任何东西,变量、函数、甚至是组件本身

function SplitPane(props) {
  return (
    <div className="SplitPane">
      <div className="SplitPane-left">
        {props.left}
      </div>
      <div className="SplitPane-right">
        {props.right}
      </div>
    </div>
  )
}

function App() {
  return (
    <SplitPane
      left={
        <Contacts />
      }
      right={
        <Chat />
      } />
  )
}

React 官方也希望我们通过组合的方式来使用组件,如果你想实现一些非界面类型函数的复用,可以单独写在其他的模块当中在引入组件进行使用

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文