React-自学之路(一)

  1. 一、自述
  2. 二、React
  3. JSX
  4. 状态机
    1. setState
    2. Props
  • 页面刷新
  • 单向数据流-Redux
  • Immutable
  • 三、虚拟DOM
  • 节点类型不同
  • 节点类型相同
  • 列表节点比较
  • 一、自述

    开发之路断断续续使用过React-Native用于开发项目。虽然更多专注与需求的快速开发,很多使用的技术也都只是了解后直接使用,简直有些无脑。但是需求已经完成,开发也已经结束,在此也需要进行一次复盘。

    作为一直使用强语言,而第一次使用弱语言(JavaScript)开发的我,简直是对其感到害怕,没有完整编辑器、代码提示、页面显示效果、更没有对 React-Native 有深入的了解下就使用 Redux 进行状态维护。没错,我从入门到跑路,抵触的心从一开始就深深扎入。

    WebStore、VS-Code、Vim。编辑器也是不停的转换,来渴望在开发过程中,找到强语言时开发的感觉。

    ES6、Flex、Redux、Immutable。React的学习也是不停的深入,也使作为小白的我有了不同的心态和看法。

    所有文章也只是我的个人看法和了解,也会不停的更新。

    二、React

    JSX

    JSX作为React的核心语言部分,使用XML标记的方式直接声明界面。

    var React = require(‘React’);
    var message =
    <div class=“hello” onClick={someFunc}>
    <span>Hello World</span>
    </div>;
    React.renderComponent(message, document.body);

    据说此次的嵌入组合相对于JavaScript也是接近于疯狂的事情,将界面与业务分离的理念也被再一次颠覆。但是在熟悉开发后发现,此方式更直观的降低React的开发学习门槛,代码也极容易理解。

    状态机

    而使JSX更直观的原因就是React的理念为一个状态机。组件的开发已经是很早就推荐的开发方式,用于提高复用和精简组件间逻辑的目的。但是React的组件却与之不同:

    所谓组件,就是状态机器
    React 将用户界面看做简单的状态机器。当组件处于某个状态时,那么就输出这个状态对应的界面。通过这种方式,就很容易去保证界面的一致性。
    在 React 中,你简单的去更新某个组件的状态,然后输出基于新状态的整个界面。React 负责以最高效的方式去比较两个界面并更新 DOM 树。

    setState

    对组件的管理就是对状态的管理。其不同与其他框架或多或少的会双向交互、数据返回的必要性(当然React也因需求需要该功能)。在React中,我们只需要setState({...})来完成对组件的状态进行更改,而相应UI的显示与其状态进行绑定,也就解决了逻辑与UI的通信问题。

    Props

    在React中组件可以作为基本单位,而在交互中除了 State(状态)外,还有就是 Props(属性)。State 更像是组件内部的自状态管理,完成对自己内部UI的控制,而Props则在对组件进行初始化中,完成了其相应功能,因此在相较于State的状态可改变,Props则推荐不可改变的数据,只用于读取。

    this.state = {
    btnState: this.props.btnState
    };

    页面刷新

    可以看到React是一个两层的编程模型:数据模型驱动 UI 界面。在数据变动后完成UI界面的变动(刷新)。刷新更像是对页面的刷新描述,当然也确实是。但是在界面及其复杂的时候,只是为了变动一个小小的参数,而刷新整个页面,代价实在太大了。因此为了解决这个问题,React使用局部UI组件刷新的概念。

    由于组件的出现,完成了UI的逻辑状态的自管理。而完成这些组件的自刷新就是:虚拟DOM(Virtual DOM)。这个词相较于了解React的各位相信都很清楚:

    简而言之就是,UI 界面是一棵DOM 树,对应的我们创建一个全局唯一的数据模型,每次数据模型有任何变化,都将整个数据模型应用到UI DOM 树上,由React 来负责去更新需要更新的界面部分。
    这使得React极大的提高性能,也将”组件化”这一理念更执行的透彻。

    单向数据流-Redux

    只有遇到React实在解决不了的问题,你才需要Redux。
    虽然使用state来进行自身状态管理。但是在大型项目时会发现React的通信机制依旧无法满足大型项目,也就需要Redux来完成更庞大的数据通信。
    Redux是一个数据流管理框架,与React最大相同点他们都偏向单项数据流,因此更符合React的数据管理理念。

    Immutable

    用于建立一个数据模型,用于对特殊数据的管理(只读数据)。面对网络请求后立即加载至UI,使代码更有利于维护性、安全性。

    三、虚拟DOM

    Web页面都是由DOM树而来。React会根据当前的状态来决定界面。当DOM某个节点发生变化,就会生成一个新的状态DOM,将两者进行比较,选择变化后的DOM树完成新的界面映射。这就需要对DOM树的Diff算法分析。

    在发生上述状况下一般由两者情况需要刷新DOM树:

    1.节点类型不同(节点ID不同)
    2.节点类型相同,但是属性不同

    节点类型不同

    当在树中的同一位置前后输出了不同类型的节点,React 直接删除前面的节点,然后创建并插入新的节点。
    当删除的节点下由自节点,那么这些子节点也会被完全删除,不会进行比较,这也是算法复杂度降低的原因之一。

    可以看出,React在进行Diff算法比较时,只会对树进行简单的逐层节点比较。当发现某个节点类型不同时会直接进行简单的节点删除、节点新增的功能。当然,这也并没有导致严重的性能问题。

    点击这个链接可以看看Diff节点的变化与生命周期的关系

    节点类型相同

    第二种节点的比较是相同类型的节点,算法就相对简单而容易理解。React 会对属性进行重设从而实现节点的转换。虚拟 DOM 的 style 属性稍有不同,其值并不是一个简单字符串而必须为一个对象,因此直接进行对象的删增。

    列表节点比较

    列表节点的操作通常包括添加、删除和排序。当数量过大则会出现性能的问题,如果每个节点都没有唯一的标识,React 无法识别每一个节点,那么更新过程会很低效。

    点击这个链接可以看看Diff节点的变化与生命周期的关系
    在shape5转换为shape6时发现如果有标识(key)的优化引导则大大减少生命周期函数调用及DOM树变化:
    加入Key前:

    B will unmount.
    C will unmount.
    C is created.
    B is created.
    C did mount.
    B did mount.
    A is updated.
    R is updated.

    加入Key后:

    C is updated.
    B is updated.
    A is updated.
    R is updated.

    这也为我对React的优化有了方向。