美文网首页
react、redux的设计理念梳理

react、redux的设计理念梳理

作者: 贪得_3440 | 来源:发表于2021-03-30 14:59 被阅读0次

针对reactreduxmobx-react的概念梳理

主题:

本次培训主要侧重于思想,具体的实现方式各自参照官网,都有详尽的描述
设计思想上的理解可能相对更需要讲解一下,所以本次培训与之前的vue不同,侧重于概念引导

目标:

  • 理解spa设计理念
  • 理解react设计理念
  • 理解redux设计理念
  • 理解mobx设计理念

目标人群:

  • 有一定的MVVM知识基础
  • 上手过MVVM的项目,理解各种情况的下的通信方式

技术文档:

1. SPA(Single Page APP)

介绍react之前,先要介绍一下SPA。

  • 什么是SPA?

    顾名思义,单页应用。
    概念上区别于传统的jsp,页面的刷新根据服务器的响应内容构造,本质上是不同的html文件的交替展示。
    单页应用的渲染只会在一个html中不断更新DOM树。

  • 为什么使用SPA?
    1. 前后端分离的最优解。

      RESTFUL API和AJAX为桥梁,将前后端的关注点彻底剥离开
      后端工程师不需要再操心数据如何嵌套入页面,专心投入到业务逻辑中去。
      前段工程师不需要再操心数据要如何取得以及保存,专心投入到用户交互中去。
      技术栈的剥离也轻松完成
      2. 服务器压力减小。
      > 服务器不需要再操心页面的构建,返回内容中不会再有大量的html文本,极大增加吞吐能力。
      3. 提高可复用率。
      > 不再需要像过往一样,为PC,手机,平板单独进行开发,一套API甚至一套前段代码可以胜任各种场景。

2. JSX

  1. 关注点分离:

    区别于angular的htmlcssts的语法分离解耦方式
    jsx以组件为单位,将构成组件所关注的内容揉在一个jsx文件内。
    此举有利有弊
    利在于可以更直观方便得清楚此组件的工作方式
    弊在于大量代码存在时结构不太分明

    helloWorld.jsx:

      // 常量定义(ts)
      const name = 'Josh Perez';
    
      // render函数内定义标签内容(html)
      public render(): JSX.Element {
        return (
          <h1>Hello, {name}</h1>;
        );
      }
    

3. REACT:

  1. 组件

    • 页面的最小组成单位,可以将其理解为一块积木。

      一个完整的页面是由无数个积木组成,而根据需求可以将积木随意搭配组合,进而构建出不同的页面。
      + 低耦合的可复用化单位
      > 在SPA应用编程中,组件化的概念必须深入人心,这样才能做出结构清晰,逻辑干净的工程

  2. props

    组件接收参数的单位。概念等同于angular的@Input

      // Clock组件
      class Clock extends React.Component {
        render() {
          return (
            <div>
              <h1>Hello, world!</h1>
              <h2>It is {this.props.date}.</h2>
            </div>
          );
        }
      }
    
      // App组件
      class App extends React.Component {
        render() {
          return (
            <Clock
              date="2019-01-01"
            />
          );
        }
      }
    
  3. state:

    区别于props,state是组件的私有状态,不与父组件产生交互

  4. 渲染表达式:

    react的风格与angular、vue不同,渲染标签的逻辑更像传统的jsp。

      class Clock extends React.Component {
        render() {
          return (
            <div>
              <h1>Hello, world!</h1>
              // 类比*ngIf
              if (this.props.showDate) {
                <h2>It is {this.props.date}.</h2>
              }
    
              <ul>
                // 类比*ngFor
                {props.list.map((post) =>
                  <li key={post.id}>
                    {post.title}
                  </li>
                )}
              </ul>
            </div>
          );
        }
      }
    
  5. 关于状态提升以及单向数据流:

    • 在react的世界里,数据是自上而下流动的,即单向数据流

      1. 设计理念

        这里先来看一下react组件的构造思想,每一个组件可以认为是一个函数,由更大的函数对其进行调用,传参,操作其返回值
        还是这个例子

          // Clock组件 将其理解为函数定义 function clock(date)
          class Clock extends React.Component {
            render() {
              return (
                <div>
                  <h1>Hello, world!</h1>
                  <h2>It is {this.props.date}.</h2>
                </div>
              );
            }
          }
        
          // App组件
          class App extends React.Component {
            render() {
              return (
                // 此处理解为函数调用 clock(date),返回值为一个div
                <Clock
                  date="2019-01-01"
                />
              );
            }
          }
        

        为什么要讲函数设计呢?
        纯函数与非纯函数的区别,就是非纯函数可能会产生副作用,即对传入的参数进行了修改。
        而react的设计理念中,一个组件就是一个纯函数,他接收参数,但不会对其进行修改。

          // 纯函数
          // 对于相同的参数总是返回相同的结果
          function getSquare(x) {
            return x * x;
          }
        
          // 非纯函数
          function getSquare(items) {
            var len = items.length;
            for (var i = 0; i &lt; len; i++) {
              items[i] = items[i] * items[i];
            }
            return items;
          }
        
      2. 实现方式

        假如需求变为一个组件可以显示时间,并且可以修改
        此处相当于将angular的双向绑定语法糖拆散

          // App组件
          class App extends React.Component {
            handleChange(e) {
              this.setState({date: e.target.value});
            }
        
            render() {
              return (
                <Clock
                  date="2019-01-01"
                  // 将数据及数据变化后应该做什么告知子组件
                  onDateChange={this.handleChange}
                />
                <Time 
                  date={this.state.date}>
              );
            }
          }
        
          class Clock extends React.Component {
            // 外部数据变化时,调用外部指示的方法
            handleChange(e) {
              this.props.onDateChange(e.target.value);
            }
        
            render() {
              return (
                <div>
                  <h1>Hello, world!</h1>
                  <input value={this.props.date} onChange={this.handleChange} />
                </div>
              );
            }
          }
        
      3. 设计优势

        • 所有状态的变化可追溯

        父组件维护了一个状态,假设子组件可随意更改父组件甚至祖宗组件的状态
        那各组件的状态改变就会变得难以追溯,父组件的状态也可能被子组件意外修改而不可察觉。
        而单向数据流的设计会严格掌控状态的变化,所有的状态变化都是由编码者所控制的。
        这样的程序在工程壮大后可维护性会显著增强

        实现方式很多,比如:

        1. 调用父组件传进来的方法
        2. 在子组件中dispatch一个action来对全局状态修改
        3. 全局状态在通过props分发给子组件
        4. 子组件推送一个事件,订阅方捕获变化
    • 状态提升

      当APP组件中存在以下两个组件:
      【1】可以修改并展示时间的组件
      【2】【1】修改后的时间format处理后展示
      这时【1】组件的状态变化后,【2】组件必须也能捕捉到,进而进行format展示
      所以状态需要保存在APP组件内,由APP控制业务流的流转。
      详细介绍可以参照官网:状态提升

  6. 关于双向绑定:

    angular的双向绑定本质是value + onChange的语法糖。
    react没有这样的语法糖,严格将状态变化的控制交到程序员手中
    参照5-2(单向数据流-实现方式)

  7. 进阶:

    设计理念理解之后,就可以参照官网进行进阶学习了。
    react官方文档

4.REDUX

  1. 先上一个思考题,有如下APP:

    E需要实时渲染D中变化的值

      // A
      <div>
        <B/>
        <E/>
      </div>
    
      // B
      <C/>
    
      // C
      <D/>
    
      // D
      <input value="name"/>
    
      // E
      <p>name</p>
    

    根据单向数据流以及状态提升的规则,需要在A组件中定义“name”,以及“onNameChange”回调
    然后一路传给B、C、D。
    D中发生变化时,再将状态变化事件一路回传给A
    A接收到变化后,再将变化后的值交给E去渲染。

    很显然,这个数据流的传递又臭又长,可能会让你怀疑自己的工作是不是太弱智了些
    于是,REDUX诞生了

  2. REDUX干了些什么?

    redux创造了APP的单一数据源概念,以依赖注入概念的实现方式,将组件的耦合性彻底打散
    redux相对于react来说,可以理解为全局状态,独立于组件树之外。
    使用方式参照官网REDUX

    • redux的解决方案

      假设在redux中定义一个变量name,D需要表示并修改name
      所以redux将name作为prop传递给D,将onNameChange作为action分发给D
      当name发生变化时,D来触发action,告知redux更新name

      E需要表示name,所以redux将name作为prop传递给E,当全局状态发生变化时,自动更新传递给E的name

    • redux的优势

      经过redux的洗礼,与name状态无关的A、B、C组件完全没有意识到name的存在
      他们可以更为专注得去完成自己的任务,而不用操心其他的数据传递任务
      从敲出来的代码,到设计上的思想,都彻底得完成了去耦

    • redux的劣势

      redux的设计为纯函数式,每一个小状态的变化会重新返回一个新的,完整的全局状态。
      当状态无比庞大时,一次更新的消耗是巨大且负担不起的
      所以当你的工程会有庞大数据量的时候,选择redux请三思
      那么当数据量无比庞大时,就没有办法了吗?

5.MOBX-REACT

  1. mobx的解决方案

    当数据量很大时,redux的全局状态深度拷贝工作变得非常臃肿,内存及CPU资源会被压榨得喘不过气
    于是mobx做出了面向对象的设计,将状态的变化锁定至对象中的某个属性,
    一次变化只会针对全局状态中的某个小属性进行修正,资源问题得以解决。
    具体使用方式,参照官网mobx-react

相关文章

  • react、redux的设计理念梳理

    针对react和redux和mobx-react的概念梳理 主题: 本次培训主要侧重于思想,具体的实现方式各自参照...

  • 第1.3章:Redux数据传递框架

    1、Redux简介 Redux的设计理念是把数据放到Store里,统一管理 2、Redux工作流程 蓝色React...

  • redux入门

    什么是redux redux是一个状态管理工具。react设计理念是单向数据流,而我们在用react构建前端应用的...

  • react和redux的连接

    React-Redux 知识梳理 Redux API createStore Store combineReduc...

  • 有标题的文章

    React Redux 路由设计 - - React

  • 0 常用三方

    动画 - react-transition-group; 设计 Ant Design of React 数据 redux

  • 从Flux到Redux

    单向数据流框架的始祖FluxFlux理念的一个更强实现Redux结合React和Redux 认识Flux flux...

  • 03|从Flux到Redux

    单向数据流始祖 Flux Flux理念的一个更强实现Redux 结合React和Redux 01|Flux 从Fl...

  • Redux for ReactNative (二)

    安装 React Redux Redux不包含React库,需要单独安装React 绑定库 react-redux...

  • redux

    单独使用redux redux是核心库 与react配合使用redux 安装react-redux react-r...

网友评论

      本文标题:react、redux的设计理念梳理

      本文链接:https://www.haomeiwen.com/subject/trhghltx.html