简评:组件(component)是 React 的核心,了解它们有助于构建好的设计结构。

什么是组件(component)

组件运行你将 UI 拆分为独立的可重用的部分。和 JavaScript 函数类似,组件接收名为 props 的输入并返回 React 元素,它描述(声明)用户界面应该是什么样子的。这就是 React 被称为声明性 API 的原因,你只需要声明你希望得到的 UI ,之后 React 负责具体的细节。

组件 API

当安装 React 后,便可以使用 React 提供的 API,基本可以分成 5 种。

  • render
  • state
  • props
  • context
  • lifecycle events

虽然组件可以使用所有的 API,但是通常一个组件只使用部分的 API,我们可以对使用不同 API 的组件进行细分,分成有状态(stateful) 和无状态(stateless) 两种组件。

  • 有状态组件使用(render,state 和 生命周期相关事件)
  • 无状态组件使用 (render,props 和 context)

这样将数据逻辑和 UI 表现层进行分离,通过组件之间划分职责可以创建更多可重用的组件,在构建可扩展的应用程序时尤为重要。

组件模式

通常组件模式有以下几种:

  • Container
  • Presentational
  • 高阶组件(Higher order components 【HOC’s】)
  • Render callback

container

容器组件(container component )负责获取数据然后渲染部分交给相应的子组件来负责。

容器是你的数据或逻辑层并利用 stateful API,使用生命周期事件你可以连接 state 到 redux 或 flux 的 storage 中。在容器组件的 render 方法中,你可以使用 Presentational 组件来渲染具体的样式。

注意:由于容器组件需要使用 stateful api ,所以容器组件需要定义成类而不能是一个纯函数。

我们来定义一个 组件 Greeting,他具有状态,生命周期 componentDidMount 事件 和 render 方法。

class Greeting extends React.Component {
constructor() {
super();
this.state = {
name: "",
};
} componentDidMount() {
// AJAX
this.setState(() => {
return {
name: "William",
};
});
} render() {
return (
<div>
<h1>Hello! {this.state.name}</h1>
</div>
);
}
}

现在我们对 Greeting 进行改进,将其分离成容器组件(container component)和展示组件(presentational component)。

Presentational

Presentational components 使用 props,render,和 context (stateless API's) ,并且由于不需要使用生命周期相关api,我们可以使用纯函数来简化表述它们:

const GreetingCard = (props) => {
return (
<div>
<h1>Hello! {props.name}</h1>
</div>
)
}

Presentational components 只从 props 获取数据和回调函数,props 由容器组件提供。

容器组件和展示组件各自将数据/逻辑和展示部分封装到各自的组件中:

const GreetingCard = (props) => {
return (
<div>
<h1>{props.name}</h1>
</div>
)
} class Greeting extends React.Component {
constructor() {
super();
this.state = {
name: "",
};
} componentDidMount() {
// AJAX
this.setState(() => {
return {
name: "William",
};
});
} render() {
return (
<div>
<GreetingCard name={this.state.name} />
</div>
);
}
}

高阶组件(Higher order components【HOC’s】)

高阶组件是一个接收一个组件作为参数然后返回全新组件的函数。

这是一种强大的模式,我们可以对输入组件的 props 进行修改(增删改查)然后返回全新的修改后的组件,例如 react-router-v4 的 withRouter() 方法可以包装任何自定义组件,将 react-router 的 history,location,match 三个对象传入,不需要一级级传入。例如 Redux,你可以使用 connect({})() 方法来将展示组件和 store 中的数据进行连接。

代码演示:

import {withRouter} from 'react-router-dom';

class App extends React.Component {
constructor() {
super();
this.state = {path: ''}
} componentDidMount() {
let pathName = this.props.location.pathname;
this.setState(() => {
return {
path: pathName,
}
})
} render() {
return (
<div>
<h1>Hi! I'm being rendered at: {this.state.path}</h1>
</div>
)
}
} export default withRouter(App);

导出组件时,我使用 react-router-v4 的 withRouter() 来封装它。在 componentDidMount 这个生命周期中,我们使用 this.props.location.pathname 来更新我们的 state,由于我们使用了 withRouter 高阶组件,我们可以直接访问 this.props.locationlocation,而不需要直接将 location 作为 props 直接传入,非常方便。

Render callbacks

与高阶组件类似,render callbacks 或 render props 可以用来重用逻辑。

class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0,
};
} increment = () => {
this.setState(prevState => {
return {
count: prevState.count + 1,
};
});
}; render() {
return (
<div onClick={this.increment}>{this.props.children(this.state)}</div>
);
}
} class App extends React.Component {
render() {
return (
<Counter>
{state => (
<div>
<h1>The count is: {state.count}</h1>
</div>
)}
</Counter>
);
}
}

在 Counter 类中,我们 render 中嵌入 this.props.childrn 并将 this.state 作为参数。在 App 类下面,我们可以将我们组件包装在 Counter 组件中。

Counter 组件的本质是暴露了 children 这个外部属性,将 children 具体的渲染细节交个 Counter 的使用者,使用的时候只需要将组件传入到 Counter 的 children 中,当然可以使用其他参数,如果 children 不够的话。例如实现一个聊天列表每条消息有头像和消息内容,具体头像是圆是方,具体消息内容是文字是图片,都交给了外部使用者。

原文:React component patterns

React 组件模式的更多相关文章

  1. React的组件模式

    组件是 React 的核心,因此了解如何利用它们对于创建优秀的设计结构至关重要. 什么是组件 根据 React 官网的介绍,"组件让你可以将 UI 分割成独立的.可重用的部分,并独立管理每个 ...

  2. jquery插件模式开发和react组件开发之间的异同

    jquery插件模式开发和react组件开发之间的异同

  3. react 反模式——不使用jsx动态显示异步组件

    前言: react反模式 (anti-patterns)指的是违背react思想(flux)的coding方式. 本文在 App 组件中,通过 Model.show 动态显示 Model 组件,通过 ...

  4. 使用reflux进行react组件之间的通信

    前言 组件之间为什么要通信?因为有依赖. 那么,作为React组件,怎么通信? React官网说, 进行 父-子 通信,可以直接pass props. 进行 子-父 通信,往父组件传给子组件的函数注入 ...

  5. React 组件开发初探

    react.js 在线地址:http://slides.com/yueyao/deck/#/ COMPONENT JSX 预编译语言, 一个基于ECMAscript 的xml-link 的语法扩展,最 ...

  6. 总结 React 组件的三种写法 及最佳实践 [涨经验]

    React 专注于 view 层,组件化则是 React 的基础,也是其核心理念之一,一个完整的应用将由一个个独立的组件拼装而成. 截至目前 React 已经更新到 v15.4.2,由于 ES6 的普 ...

  7. react 组件的生命周期

    组件的生命周期 过程 装载(Mounting) :组件被插入到 DOM 中: 更新(Updating) :组件重新渲染以更新 DOM: 卸载(Unmounting) :组件从 DOM 中移除. 过程 ...

  8. 深入React组件生命周期

    上篇博文使用React开发的一些注意要点对React开发的一些重点进行了简单的罗列总结,虽然也提到了React生命周期,但只略微小结,在此单独写篇React生命周期的总结. 在组件的整个生命周期中,随 ...

  9. 如何优雅的设计 React 组件

    作者:晓冬 本文原创,转载请注明作者及出处 如今的 Web 前端已被 React.Vue 和 Angular 三分天下,一统江山十几年的 jQuery 显然已经很难满足现在的开发模式.那么,为什么大家 ...

随机推荐

  1. oracle中如何修改process

    转自https://blog.csdn.net/qq_35686181/article/details/52350922 oracle中修改process  在 oracle中,要经常查看proces ...

  2. ICG游戏:斐波那契博弈

    描述: 有一堆个数为n(n>=2)的石子,游戏双方轮流取石子,规则如下: 1)先手不能在第一次把所有的石子取完,至少取1颗: 2)之后每次可以取的石子数至少为1,至多为对手刚取的石子数的2倍: ...

  3. 37-python中bs4获取的标签中如何提取子标签

    如果只是要提取一个标签 里面的属性值啥的,直接看这篇文章就可以了: 23-python用BeautifulSoup用抓取a标签内所有数据 如果是标签的嵌套,可以参考下面的思路,虽然不是很简洁,但是可以 ...

  4. MFC The Screen Flickers When The Image Zoomed

    问题描述 当初写MFC也是不情愿的. 既然写了,遇到一些问题. 解决也废了一切功夫.所以简单的记录一下. 这个问题,也就是使用MFC显示图像的时候, 放缩图像的过程中, 图像会一闪一闪的. 这个问题的 ...

  5. dedecms实例化对象

    1.建表 2.创建实体类 4.tc文件加载该实体类 5.用的时候,引入tc.php文件,并实例化

  6. 马婕 2014MBA专硕考试 词汇每日一练(转)

    2013-6-8 1. To ensure its sustained progress in economy, the government has _______ a series of poli ...

  7. Chrome Console API 参考

    https://developers.google.com/web/tools/chrome-devtools/console/command-line-reference

  8. UVa 1606 Amphiphilic Carbon Molecules (扫描法+极角排序)

    题意:平面上有 n 个点,每个点不是黑的就是白的,现在要放一个隔板,把它们分成两部分,使得一侧的白点数加上另一侧的黑点数最多. 析:这个题很容易想到的就是暴力,不妨假设隔板至少经过两个点,即使不经过也 ...

  9. ADO接口之_RecordsetPtr

    转自:http://hi.baidu.com/%CE%D2%B6%CF%C1%CB%CB%BC%C4%EE/blog/item/e057c526c6af6c29c995596e.html _Recor ...

  10. 通过HttpClient请求webService

    通过HttpClient请求webService 由于服务端是用webService开发的,android要调用webService服务获取数据,这里采用的是通过HttpClient发送post请求, ...