在React开发中,一个典型的React组件通常会混杂着逻辑操作部分和展示部分。逻辑操作部分指的是和页面UI无关的内容,如API的调用,数据的处理,事件处理函数。 展示部分则指的是创建页面UI 的内容,就是组件中render 函数的内容。

  简单地写一个组件Geo 来看一下,这个组件会展示我们的位置信息。为了简单起见,用create-react-app创建项目。项目中的src目录主要存放源代码,所以我们在其内部新建一个目录components, 用于存放我们的组件。一般我们直接写js 文件,暴露出我们的组件,供其他组件使用。在components 目录下新建Geo.js 文件,代码如下,很简单,由于展示经纬度,所以需要两个状态: lon/lat, 分别表示经度/纬度;同时,组件渲染完成后,在其生命周期函数componentDidMount 下调用html5 的navigator Api 获取经纬度。

  1. import React, {Component} from 'react';
  2.  
  3. export default class Geo extends Component {
  4. constructor(props) {
  5. super(props);
  6. this.state = {
  7. lat: null, // 纬度
  8. lon: null // 经度
  9. }
  10.  
  11. this.handleSucess = this.handleSucess.bind(this)
  12. }
  13.   //调用navigator API 获取当前的位置
  14. componentDidMount() {
  15. if(navigator.geolocation) {
  16. navigator.geolocation.getCurrentPosition(this.handleSucess)
  17. }
  18. }
  19.   // 位置获取成功后的回调函数
  20. handleSucess({coords}) {
  21. var lat = coords.latitude.toFixed(2);
  22. var lon = coords.longitude.toFixed(2);
  23. this.setState({
  24. lat ,
  25. lon
  26. })
  27. }
  28.  
  29. render() {
  30. return (
  31. <div>
  32. <div>纬度: {this.state.lat}</div>
  33. <div>经度: {this.state.lon} </div>
  34. </div>
  35. )
  36. }
  37. }

  然后在App.js 中 引入Geo组件,就是在App.js 文件上部写下

  1. import Geo from './components/Geo';

  并将App render 函数中以下代码

  1. <p className="App-intro">
  2. To get started, edit <code>src/App.js</code> and save to reload.
  3. </p>

  改为

  1. <div className="App-intro">
  2. <Geo />
  3. </div>

  这时页面可以看到经纬度的展示,在chrome 需要FQ,因为他调用的是google地图,你可以用手机看一下效果

  很明显地可以看到逻辑和展示的混杂。Navigator API 就是逻辑操作,render函数则是纯展示部分。

  这时我们看一下容器和展示模式。容器和展示模式指的是把组件的逻辑操作部分和展示部分进行分离,分别放到不同的文件中,这样,每一个组件都会分成两个部分,两者都有各自的职责,一个只负责操作逻辑,叫做容器container, 一个只负责页面展示,叫做展示Presentational。 现在把我们的Geo 组件按照容器和展示模式进行一下拆分,这时新建一下js 文件,命名为Geo-container.js,它是一个容器组件,书写页逻辑,那么原来的Geo.js文件就变成了纯渲染组件。这种命名规则是React社区的规范,加container 后缀表示容器组件,不加则表示展示组件。

  Geo-container.js 内容如下,它是直接把展示组件引入,然后对其进行传参

  1. import React, {Component} from 'react';
  2. import Geo from './Geo' // 引进展示组件
  3.  
  4. export default class GeoContainer extends Component {
  5. constructor(props) {
  6. super(props);
  7. this.state = {
  8. lat: null, // 纬度
  9. lon: null // 经度
  10. }
  11.  
  12. this.handleSucess = this.handleSucess.bind(this)
  13. }
  14.  
  15. componentDidMount() {
  16. if(navigator.geolocation) {
  17. navigator.geolocation.getCurrentPosition(this.handleSucess)
  18. }
  19. }
  20.  
  21. handleSucess({coords}) {
  22. var lat = coords.latitude.toFixed(2);
  23. var lon = coords.longitude.toFixed(2);
  24. this.setState({
  25. lat ,
  26. lon
  27. })
  28. }
  29. // 在容器组件内部,只渲染我们引入的展示组件,并把状态当做参数进行传递
  30. render() {
  31. return (<Geo {...this.state}/>)
  32. }
  33. }

  Geo.js 由于变成了纯渲染组件,所以用无状态组件的样式进行书写,

  1. import React from 'react';
  2.  
  3. // 由于展示组件内部没有任何的状态,只负责展示,所以用无状态组件。
  4. const Geo = ({lat,lon}) => {
  5. return (
  6. <div>
  7. <div>纬度: {lat}</div>
  8. <div>经度: {lon} </div>
  9. </div>
  10. )
  11. }
  12.  
  13. export default Geo

  在App.js中直接引入容器组件

  1. import React, { Component } from 'react';
  2. import logo from './logo.svg';
  3. import './App.css';
  4.  
  5. import GeoContainer from './components/GeoContainer'; // 引入我们的空器组件
  6.  
  7. class App extends Component {
  8. render() {
  9. return (
  10. <div className="App">
  11. <div className="App-header">
  12. <img src={logo} className="App-logo" alt="logo" />
  13. <h2>Welcome to React</h2>
  14. </div>
  15. {/*渲染我们的容器组件*/}
  16. <div className="App-intro">
  17. <GeoContainer />
  18. </div>
  19. </div>
  20. );
  21. }
  22. }
  23.  
  24. export default App;

  这样同样实现了我们的功能,但职责更为了清晰,组件更容易被复用

React 设计模式 --- Container and Presentational pattern(容器和展示组件分离)的更多相关文章

  1. React 之容器组件和展示组件相分离解密

    Redux 的 React 绑定库包含了 容器组件和展示组件相分离 的开发思想.明智的做法是只在最顶层组件(如路由操作)里使用 Redux.其余内部组件仅仅是展示性的,所有数据都通过 props 传入 ...

  2. 关于React的Container&Presentational Component模型结构分析

    react.js javascript 3 之前翻译了两篇关于Container&Presentational Component模型的文章,一篇是基础的Container和Component ...

  3. 展示组件(Presentational component)和容器组件(Container component)之间有何不同

    展示组件关心组件看起来是什么.展示专门通过 props 接受数据和回调,并且几乎不会有自身的状态,但当展示组件拥有自身的状态时,通常也只关心 UI 状态而不是数据的状态.(子组件)容器组件则更关心组件 ...

  4. React容器组件和展示组件

    Presentational and Container Components   展示组件   - 只关心它们的样子.   - 可能同时包含子级容器组件和展示组件,一般含DOM标签和自定的样式.   ...

  5. React设计模式相关

    关于我在React设计模式上做的一些思考: 一,项目里实战的经历 最开始我根据组件不同的职能定义,拆分了展示组件和容器组件两大类,后来随着业务逻辑越来越复杂,容器组件代码越来越冗长,我又加入了HOC高 ...

  6. 说说设计模式~大话目录(Design Pattern)

    回到占占推荐博客索引 设计模式(Design pattern)与其它知识不同,它没有华丽的外表,没有吸引人的工具去实现,它是一种心法,一种内功,如果你希望在软件开发领域有一种新的突破,一个质的飞越,那 ...

  7. 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)

    原文:乐在其中设计模式(C#) - 观察者模式(Observer Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 观察者模式(Observer Pattern) 作者:weba ...

  8. 乐在其中设计模式(C#) - 装饰模式(Decorator Pattern)

    原文:乐在其中设计模式(C#) - 装饰模式(Decorator Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 装饰模式(Decorator Pattern) 作者:weba ...

  9. 乐在其中设计模式(C#) - 适配器模式(Adapter Pattern)

    原文:乐在其中设计模式(C#) - 适配器模式(Adapter Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 适配器模式(Adapter Pattern) 作者:webabc ...

随机推荐

  1. JS中caller和callee

    caller: caller是函数对象的一个属性,指的是这个函数对象的调用者,如果调用者,如果是顶层调用者,则返回null. 例: function func(){ console.log(func. ...

  2. 从零开始搭建django前后端分离项目 系列三(实战之异步任务执行)

    前面已经将项目环境搭建好了,下面进入实战环节.这里挑选项目中涉及到的几个重要的功能模块进行讲解. celery执行异步任务和任务管理 Celery 是一个专注于实时处理和任务调度的分布式任务队列.由于 ...

  3. Android hook神器frida(二)

    1.关于使用frida遇到的一些问题 (1)如果出现以下错误: 可以通过以下方式关闭SELinux,在adb shell中执行: > /sys/fs/selinux/enforce 或者 set ...

  4. .NetCore简单学习图谱

    一.学习途径 学习.netcore的最佳途径在哪里,无疑是微软官方.netCore指南.它覆盖十分全面,就目前网上经常看到的各种文章都能在微软处找到类似文章,堪称.netcore的百科全书.所以我利用 ...

  5. RPM打包原理、示例、详解及备查

    原文地址:https://blog.csdn.net/qq_16542775/article/details/80961213 RPM(Redhat Package Manager)是用于Redhat ...

  6. Python-TXT文本操作

    一.列出IO操作的标识符及描述 标识符 描述 r 以只读方式打开文件.文件的指针将会放在文件的开头.这是默认模式. rb 以二进制格式打开一个文件用于只读.文件指针将会放在文件的开头.这是默认模式. ...

  7. H5 56-还原字体和字号

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. 使用git将本地项目推送到码云私有仓库

    https://blog.csdn.net/qq_33876553/article/details/80111946 2018年04月27日 19:53:33 桥路丶 阅读数:2958 前言 之前博主 ...

  9. 解决Window安全中心对Kitematic-0.17.3-Ubuntu.zip提示病毒,但无法删除的问题。

    Trojan:JS/Tisifi.B 类型:特洛伊木马 containerfile: C:\Users\Administrator\Desktop\Kitematic-0.17.3-Ubuntu.zi ...

  10. pip ipython启动错误 Fatal error in launcher: Unable to create process using

    完整的错误提示: C:\Users\yyy>ipython3Fatal error in launcher: Unable to create process using '"c:\u ...