文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
四、组件类型
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论