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;

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

时间: 2024-10-05 23:09:20

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

关于React的Container&amp;Presentational Component模型结构分析

react.js javascript 3 之前翻译了两篇关于Container&Presentational Component模型的文章,一篇是基础的Container和Component的定义,另外一篇是进阶版,因为翻译的太烂,感觉有很多错误,所以只放原文链接. 在这里我想讨论一下我自己对这个模型的一些想法. 注:便于书写,下面统一把Container&Presentational Components模型翻译为容器&展示组件模型 注:下面图片中的components文件夹指

设计模式 - 代理模式(proxy pattern) 未使用代理模式 详解

代理模式(proxy pattern) 未使用代理模式 详解 本文地址: http://blog.csdn.net/caroline_wendy 部分代码参考: http://blog.csdn.net/caroline_wendy/article/details/37698747 如果需要监控(monitor)类的某些状态, 则需要编写一个监控类, 并同过监控类进行监控. 但仅仅局限于本地, 如果需要远程监控, 则需要使用代理模式(proxy pattern). 具体方法: 1. 类中需要提供

设计模式 - 迭代器模式(iterator pattern) Java 迭代器(Iterator) 详解

迭代器模式(iterator pattern) Java 迭代器(Iterator) 详解 本文地址: http://blog.csdn.net/caroline_wendy 参考迭代器模式(iterator pattern): http://blog.csdn.net/caroline_wendy/article/details/35254643 Java的标准库(util)中包含迭代器接口(iterator interface), import java.util.Iterator; 继承(

设计模式 - 外观模式(facade pattern) 详解

外观模式(facade pattern) 详解 本文地址: http://blog.csdn.net/caroline_wendy 外观模式(facade pattern): 提供了一个统一的接口, 用来访问子系统中的一群接口. 外观定义了一个高层接口, 让子系统更容易使用. 外观模式包含三个部分: 1. 子系统: 子类, 单个复杂子类 或 多个子类; 2. 外观(facade)类: 把子系统设计的更加容易使用; 3. 客户: 只需要调用外观类. 与适配器模式(adapter pattern)的

设计模式之适配器模式(Adapter Pattern)

适配器模式(Adapter):将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作. 1. 解决的问题 即Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作. 2. 模式中的角色 2.1 目标接口(Target):客户所期待的接口.目标可以是具体的或抽象的类,也可以是接口. 2.2 需要适配的类(Adaptee):需要适配的类或适配者类. 2.3 适配器(Adapter):通过包装一个需要适配的对象,把

设计模式 - 策略模式(Strategy Pattern) 具体解释

策略模式(Strategy Pattern) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26577879 本文版权全部, 禁止转载, 如有须要, 请站内联系. 策略模式: 定义了算法族, 分别封装起来, 让它们之间能够相互替换, 此模式让算法的变化独立于使用算法的客户. 对于父类的子类族须要常常扩展新的功能, 为了使用父类比較灵活的加入子类, 把父类的行为写成接口(interface)的形式; 使用set()方法

设计模式 - 组合模式(composite pattern) 详解

组合模式(composite pattern) 详解 本文地址: http://blog.csdn.net/caroline_wendy 组合模式: 允许你将对象组合成树形结构来表现"整体/部分"层次结构. 组合能让客户以一致的方法处理个别对象以及组合对象. 建立组件类(Component), 组合类(composite)和叶子类(leaf)继承组件类, 客户类(client)直接调用最顶层的组合类(composite)即可. 具体方法: 1. 组件类(component), 包含组合

设计模式 - 单件模式(singleton pattern) 详解

单件模式(singleton pattern) 详解 本文地址: http://blog.csdn.net/caroline_wendy/article/details/28595349 单件模式(singleton pattern) : 确保一个类只有一个实例, 并提供一个全局访问点. 单价模式包括3个部分: 私有构造器, 静态变量, 静态方法. 具体方法: 1. 标准的单例模式: /** * @time 2014.6.5 */ package singleton; /** * @author

设计模式 - 组合模式(composite pattern) 迭代器(iterator) 详解

组合模式(composite pattern) 迭代器(iterator) 详解 本文地址: http://blog.csdn.net/caroline_wendy 参考组合模式(composite pattern): http://blog.csdn.net/caroline_wendy/article/details/36895627 在组合模式(composite pattern)添加迭代器功能, 遍历每一个组合(composite)的项. 具体方法: 1. 抽象组件类(abstract