react白菜一颗,人老了脑子不好用,就多写一写,愿能保持更新上来

背景和个性

  1. 传统ui操作关注细节太多
  2. 程序状态多,不好跟踪和保护

react:始终整体刷新页面,无需关怀细节

  • 一个新概念

    组件:react用组件的形式去形容ui

  • 四个API
  • 单向数据流
  • 欠缺谬误提醒

解决了ui问题,如何解决数据模型问题?

传统的MVC模式中Model和View的应用关系简单,出问题之后很难追踪问题,由此提出了Flux架构:单向数据流

当view上产生了用户操作会生成一个action,action通过Dispatcher dispatch进来交给Store解决,view绑定在store上,整体建设在状态之上进行ui的更新。这里集体了解MVC框架的劣势自身其实并不是数据的双向绑定而是外部事件机制的暗箱操作不可控,事实上VUE框架自身也通过v-model实现双向数据绑定,而当咱们不关怀表单交互过多下的业务无关代码时双向绑定能够压缩很多人工code,不好的就是黑盒下的谬误debug难度晋升,单向数据流的优缺就是镜像关系了,所以,no silver bullet

组件构建UI

传统构建表单页面个别流程是,定义HTML模版,JS拿数据并填充,提交表单时用form绑定事件实现。

react示例:

class CommentBox extends Component {    render() {        return {            <div className="comment-box">                <h1>Comments</h1>                <CommentList/>                <CommentForm/>            </div>        }    }}

CommentBox、CommentList、CommentForm就是组件,组件 = props + state ----> view,react组件的特点:

  • 不提供形式,相当于状态机
  • 组件相似于纯函数
  • 单向的数据绑定

相应的创立一个组件须要思考:

  • 动态UI:具体应用什么HTML tag
  • 组件状态组成:state来自内部or外部?
  • 组件交互方式:外部如何操作?如何裸露给内部使用者
  • 一个组件只做一件事(设计模式中的繁多职责准则),如果简单,应该做拆分
  • 状态能计算就不存储

JSX

不是模版引擎,是一种语法糖,能够在js中间接写HTML标记,

const element = <h1>hello, {name}</h1>;//相当于const element = React.creatElement('h1', null, 'Hello, ', name);//属性中用表达式 <MyComponent foo={1+2+3+4} />;//延展属性(ES6中也有)const props = {firtName: 'Ben', lastName: 'Hector'};const greeting = <Greeting {...props} />;//表达式作为子元素const element = <li>{props.message}</li>/*** 小写tag为原生,自定义大写结尾**/

用申明形式形容动态创建组件过程,能够仍然应用js个性和相熟的语法

React生命周期

三个阶段

  • render阶段:计算状态
  • pre-commit阶段:读取DOM内容
  • commit阶段:状态映射到DOM,更新节点

三个类型

  • mounting

    • constructor: 构造函数

      • 惟一能够间接批改state的阶段
    • getDerivedStateFromProps(version 16.3): 内部属性初始化外部状态

      • state从props初始化时应用,须要保护一致性,每次render都会调用(典型场景:表单默认输出)
    • render:必定义,形容UI DOM构造
    • componentDIdMount

      • UI渲染实现时调用,只执行一次
  • updating(new props: 传进新属性, setState:外部批改状态,forceUpdate:强制刷新)

    • getDerivedStateFromProps
    • shouldComponentUpdate:是否真的须要render(可优化局部,个别由PureComponent主动实现)
    • render:diff,虚构dom计算
    • getSnapshotBeforeUpdate

      • render之前调用,state曾经更新(场景:获取render之前的DOM状态)
    • componentDidUpdate

      • 每次UI更新时调用(场景:从新获取变动后的props)
  • Unmounting(组件隐没时,销毁,做一些资源开释的操作)

这里比照VUE框架两者的流程是类似的,都是经验了初始化、创立、挂载、销毁、更新,稍有不同的一点,更新过程挂载阶段react应用componentDidUpdate,vue仍然会用mounted

virtual DOM

不论是vue还是react都是通过了虚构DOM的创立和部分更新来达到更快地渲染体验(分层比拟,BFS,复杂度为O(n) )

上图的一次更新中,波及到几个次要的差别

  • A B程序替换
  • D的层级变换
  • C节点的隐没
  • G的节点的格局批改

react的解决办法(这里的diff不会关怀删除的某个节点有没有在其余中央用到,即认为DOM构造绝对稳固)

  • 第二层,获取A B惟一标识获知程序变动,替换地位
  • 第三层,F 变为 G 类型变动,删除F,append一个新节点到A上;删除D
  • 第四层,从新创立一个D(这里想当于放弃查看,因为真实情况跨层级的节点挪动并不多,可疏忽)

组件设计

高阶组件(HOC):接管组件作为参数,返回新组件

//一个简略的计时器HOCimport React from "react";export default function withTimer(WrappedComponent) {  return class extends React.Component {    state = { time: new Date() };    componentDidMount() {      this.timerID = setInterval(() => this.tick(), 1000);    }    componentWillUnmount() {      clearInterval(this.timerID);    }    tick() {      this.setState({        time: new Date()      });    }    render() {      return <WrappedComponent time={this.state.time} {...this.props} />;    }  };}//之后将withTimer imoport到想应用的js中,并export withTimer({xxxApp}),即可在xxxApp中用this.porps.time

函数作为子组件(组件如何render由应用组件的人来决定,升高scope,减少灵活性):

//MyComponent将一个函数作为children,是一种通用的设计模式思维 class MyComponent extends React.Component {    render() {        return (        <div>            {this.props.children('Nate Wang')}        </div>        )    }}<MyComponent>    {(name) => (        <div>{name}</div> //这里能够写任何UI    )}</MyComponent>

context API(version16.3新个性)

罕用场景:组件树共享全局上下文数据,不须要一层层传递。 const Context = React.creatContext('shareData');

通过Provider value="" 来提供值,Consumer state.name来获取值