React 设计模式 --- Container and Presentational pattern(容器和展示组件分离)
在React开发中,一个典型的React组件通常会混杂着逻辑操作部分和展示部分。逻辑操作部分指的是和页面UI无关的内容,如API的调用,数据的处理,事件处理函数。 展示部分则指的是创建页面UI 的内容,就是组件中render 函数的内容。
简单地写一个组件Geo 来看一下,这个组件会展示我们的位置信息。为了简单起见,用create-react-app创建项目。项目中的src目录主要存放源代码,所以我们在其内部新建一个目录components, 用于存放我们的组件。一般我们直接写js 文件,暴露出我们的组件,供其他组件使用。在components 目录下新建Geo.js 文件,代码如下,很简单,由于展示经纬度,所以需要两个状态: lon/lat, 分别表示经度/纬度;同时,组件渲染完成后,在其生命周期函数componentDidMount 下调用html5 的navigator Api 获取经纬度。
import React, {Component} from 'react';
export default class Geo extends Component {
constructor(props) {
super(props);
this.state = {
lat: null, // 纬度
lon: null // 经度
}
this.handleSucess = this.handleSucess.bind(this)
}
//调用navigator API 获取当前的位置
componentDidMount() {
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(this.handleSucess)
}
}
// 位置获取成功后的回调函数
handleSucess({coords}) {
var lat = coords.latitude.toFixed(2);
var lon = coords.longitude.toFixed(2);
this.setState({
lat ,
lon
})
}
render() {
return (
<div>
<div>纬度: {this.state.lat}</div>
<div>经度: {this.state.lon} </div>
</div>
)
}
}
然后在App.js 中 引入Geo组件,就是在App.js 文件上部写下
import Geo from './components/Geo';
并将App render 函数中以下代码
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
改为
<div className="App-intro">
<Geo />
</div>
这时页面可以看到经纬度的展示,在chrome 需要FQ,因为他调用的是google地图,你可以用手机看一下效果

很明显地可以看到逻辑和展示的混杂。Navigator API 就是逻辑操作,render函数则是纯展示部分。
这时我们看一下容器和展示模式。容器和展示模式指的是把组件的逻辑操作部分和展示部分进行分离,分别放到不同的文件中,这样,每一个组件都会分成两个部分,两者都有各自的职责,一个只负责操作逻辑,叫做容器container, 一个只负责页面展示,叫做展示Presentational。 现在把我们的Geo 组件按照容器和展示模式进行一下拆分,这时新建一下js 文件,命名为Geo-container.js,它是一个容器组件,书写页逻辑,那么原来的Geo.js文件就变成了纯渲染组件。这种命名规则是React社区的规范,加container 后缀表示容器组件,不加则表示展示组件。
Geo-container.js 内容如下,它是直接把展示组件引入,然后对其进行传参
import React, {Component} from 'react';
import Geo from './Geo' // 引进展示组件
export default class GeoContainer extends Component {
constructor(props) {
super(props);
this.state = {
lat: null, // 纬度
lon: null // 经度
}
this.handleSucess = this.handleSucess.bind(this)
}
componentDidMount() {
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(this.handleSucess)
}
}
handleSucess({coords}) {
var lat = coords.latitude.toFixed(2);
var lon = coords.longitude.toFixed(2);
this.setState({
lat ,
lon
})
}
// 在容器组件内部,只渲染我们引入的展示组件,并把状态当做参数进行传递
render() {
return (<Geo {...this.state}/>)
}
}
Geo.js 由于变成了纯渲染组件,所以用无状态组件的样式进行书写,
import React from 'react';
// 由于展示组件内部没有任何的状态,只负责展示,所以用无状态组件。
const Geo = ({lat,lon}) => {
return (
<div>
<div>纬度: {lat}</div>
<div>经度: {lon} </div>
</div>
)
}
export default Geo
在App.js中直接引入容器组件
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import GeoContainer from './components/GeoContainer'; // 引入我们的空器组件
class App extends Component {
render() {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
{/*渲染我们的容器组件*/}
<div className="App-intro">
<GeoContainer />
</div>
</div>
);
}
}
export default App;
这样同样实现了我们的功能,但职责更为了清晰,组件更容易被复用
React 设计模式 --- Container and Presentational pattern(容器和展示组件分离)的更多相关文章
- React 之容器组件和展示组件相分离解密
Redux 的 React 绑定库包含了 容器组件和展示组件相分离 的开发思想.明智的做法是只在最顶层组件(如路由操作)里使用 Redux.其余内部组件仅仅是展示性的,所有数据都通过 props 传入 ...
- 关于React的Container&Presentational Component模型结构分析
react.js javascript 3 之前翻译了两篇关于Container&Presentational Component模型的文章,一篇是基础的Container和Component ...
- 展示组件(Presentational component)和容器组件(Container component)之间有何不同
展示组件关心组件看起来是什么.展示专门通过 props 接受数据和回调,并且几乎不会有自身的状态,但当展示组件拥有自身的状态时,通常也只关心 UI 状态而不是数据的状态.(子组件)容器组件则更关心组件 ...
- React容器组件和展示组件
Presentational and Container Components 展示组件 - 只关心它们的样子. - 可能同时包含子级容器组件和展示组件,一般含DOM标签和自定的样式. ...
- React设计模式相关
关于我在React设计模式上做的一些思考: 一,项目里实战的经历 最开始我根据组件不同的职能定义,拆分了展示组件和容器组件两大类,后来随着业务逻辑越来越复杂,容器组件代码越来越冗长,我又加入了HOC高 ...
- 说说设计模式~大话目录(Design Pattern)
回到占占推荐博客索引 设计模式(Design pattern)与其它知识不同,它没有华丽的外表,没有吸引人的工具去实现,它是一种心法,一种内功,如果你希望在软件开发领域有一种新的突破,一个质的飞越,那 ...
- 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)
原文:乐在其中设计模式(C#) - 观察者模式(Observer Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 观察者模式(Observer Pattern) 作者:weba ...
- 乐在其中设计模式(C#) - 装饰模式(Decorator Pattern)
原文:乐在其中设计模式(C#) - 装饰模式(Decorator Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 装饰模式(Decorator Pattern) 作者:weba ...
- 乐在其中设计模式(C#) - 适配器模式(Adapter Pattern)
原文:乐在其中设计模式(C#) - 适配器模式(Adapter Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 适配器模式(Adapter Pattern) 作者:webabc ...
随机推荐
- # 20175329 2018-2019-2 《Java程序设计》 第二周学习总结
学号 2018-2019-3<Java程序设计>第二周学习总结 教材学习内容总结 第二三章与我们所学习的C语言有很多的相似点,在这里我想主要就以我所学习的效果来讨论一下JAVA与 ...
- Java多线程(五)——线程等待与唤醒
一.wait().notify().notifyAll()等方法介绍 在Object.java中,定义了wait(), notify()和notifyAll()等接口.wait()的作用是让当前线程进 ...
- Linux笔记-SIGHUP与daemon
参考资料:linux信号signal和sigaction理解 http://blog.csdn.net/beginning1126/article/details/8680757 signal,此函 ...
- Feature Extractor[ResNet v2]
0. 背景 何凯明大神等人在提出了ResNet网络结构之后,对其做了进一步的分析工作,详细的分析了ResNet 构建块能起作用的本质所在.并通过一系列的实验来验证恒等映射的重要性,并由此提出了新的构建 ...
- linux驱动之中断处理过程C程序部分
当发生中断之后,linux系统在汇编阶段经过一系列跳转,最终跳转到asm_do_IRQ()函数,开始C程序阶段的处理.在汇编阶段,程序已经计算出发生中断的中断号irq,这个关键参数最终传递给asm_d ...
- 深入理解跨域SSO(单点登录)原理与技术
一:SSO体系结构 SSO SSO英文全称Single Sign On,单点登录.SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.它包括可以将这次主要的登录映射到其他 ...
- 一起学习造轮子(二):从零开始写一个Redux
本文是一起学习造轮子系列的第二篇,本篇我们将从零开始写一个小巧完整的Redux,本系列文章将会选取一些前端比较经典的轮子进行源码分析,并且从零开始逐步实现,本系列将会学习Promises/A+,Red ...
- Mysql多实例添加到开机自启的方法
Mysql多实例配置成功后,想让配置成开机自启. 首先看一下Linux启动的知识点,顺序如下. 1 加载内核2 执行init程序3 /etc/rc.d/rc.sysinit # 由init执行的第 ...
- Technical Development Guide---for Google
Technical Development Guide This guide provides tips and resources to help you develop your technica ...
- 动态规划-LCS最长公共子序列
#include<iostream> #include<cstdio> #include<cstring> #include<string> using ...