理解React

作者: helloyoucan | 来源:发表于2018-06-05 08:50 被阅读68次
React v16.4.0

一、理解优点

1、虚拟DOM
2、合成事件(SyntheticEvent)

1、虚拟DOM

在React中,render执行的结果得到的并不是真正的DOM节点,而仅仅是JavaScript对象,称之为虚拟DOM。

虚拟DOM是在DOM的基础上建立了一个抽象层,对数据和状态所做的任何改动,都会被自动且高效的同步到虚拟DOM,最后再批量同步到DOM中。

虚拟DOM的原理:

React会在内存中维护一个虚拟DOM树,对这个树进行读或写,实际上是对虚拟DOM进行。当数据变化时,React会自动更新虚拟DOM,然后将新的虚拟DOM和旧的虚拟DOM进行对比,找到变更的部分,得出一个diff,然后将diff放到一个队列里,最终批量更新这些diff到DOM中。

虚拟DOM的优点:

最终表现在DOM上的修改只是变更的部分,可以保证非常高效的渲染。

虚拟DOM的缺点:

首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比innerHTML插入慢。

2、合成事件(SyntheticEvent)

因为在浏览器中直接操作DOM会占用很大的内存,并且绑定浏览器事件也会占用一定的内存(绑定事件越多,占用内存越大)。所以,React实现了一套合成系统,简化了事件逻辑,同时解决了浏览器(FF浏览器和IE浏览器)的兼容问题

基本原理是

在JSX上面声明的所有事件,都会别委托在最外层的document节点上(事件委托),并且根据事件的名和组件名存储回调函数(listenerBank),当某个组件触发事件是,在在document节点上绑定的监听函数(dispatchEvent),就会找到这个组件和它的所有父组件(ancestors),对每个组件创建对应React合成事件(SyntheticEvent)并批处理(runEventQueueInBatch(events)),从而根据事件名和组件名调用(invokeGuardedCallback)回调函数。

但是

由于React合成事件系统模拟事件冒泡的方法是构建一个自己及父组件队列,因此也带来一个问题,合成事件不能阻止原生事件,原生事件可以阻止合成事件。用 event.stopPropagation() 并不能停止事件传播,应该使用 event.preventDefault()。

二、组件的生命周期

为了更好地理解React组件的生命周期,编写了如下代码

//Father.js
import React from 'react'
import Child from './Child.js'
export default class Father extends React.Component{
constructor(){
    super()
    this.state={
      randomData:0,
      hasChild:true
    }
    console.log('father constructor')
  }
  componentWillMount(){
    console.log('father componentWillMount')
  }
  componentDidMount(){
    console.log('father componentDidMount')
  }
  componentWillReceiveProps(nextProps){
    console.log('father componentReceiveProps')
  }
  shouldComponentUpdate(nextProps,nextState){
    console.log('father shouldComponentUpdate nextProps:'
      +JSON.stringify(nextProps)
      +'------nextState:'
      +JSON.stringify(nextState))
    return true
  }
  componentWillUpdate(){
    console.log('father componentWillUpdate')
  }
  componentDidUpdate(){
    console.log('father componentDidUpdate')
  }
  componentWillUnmount(){
    console.log('father componentWillUnmount')
  }
  handleChangeState(){
    this.setState({
      randomData:Math.floor(Math.random()*100)
    })
  }
  handleChangeChild(){
     this.setState({
      hasChild:!this.state.hasChild
    })
  }

  render(){
    console.log('father render')
    return (
      <div>
          <h1>Father State ---{this.state.randomData}</h1>
          <button onClick={this.handleChangeState.bind(this)}>Change</button>
          <p><button onClick={this.handleChangeChild.bind(this)}>{this.state.hasChild?'hide':'show'}</button></p>
          {this.state.hasChild?( <Child data={this.state.randomData} />):''}
      </div>
      )
  }
}
//Child.js
import React from 'react'
export default class Child extends React.Component{
    constructor(){
        super()
        console.log('child constructor')
    }
    componentWillMount(){
        console.log('child componentWillMount')
    }
    componentDidMount(){
        console.log('child componentDidMount')
    }
    componentWillReceiveProps(nextProps){
        console.log('child componentReceiveProps')
    }
    shouldComponentUpdate(nextProps,nextState){
        console.log('child shouldComponentUpdate nextProps:'
            +JSON.stringify(nextProps)
            +'------nextState:'
            +JSON.stringify(nextState))
         return true
    }
    componentWillUpdate(){
        console.log('child componentWillUpdate')
    }
    componentDidUpdate(){
        console.log('child componentDidUpdate')
    }
    componentWillUnmount(){
        console.log('child componentWillUnmount')
    }
    render(){
        console.log('child render')
        return (<h2>child recive props---{this.props.data}</h2>)
    }
}

运行结果如下


image.png

控制台输出的内容如下

father constructor
father componentWillMount
father render
child constructor
child componentWillMount
child render
child componentDidMount
father componentDidMount

点击Change按钮,
页面变化如下


image.png

控制台输入结果如下

father shouldComponentUpdate nextProps:{}------nextState:{"randomData":18,"hasChild":true}
father componentWillUpdate
father render
child componentReceiveProps
child shouldComponentUpdate nextProps:{"data":18}------nextState:null
child componentWillUpdate
child render
child componentDidUpdate
father componentDidUpdate

点击hide按钮,
页面变化如下


image.png

控制台输入结果如下

father shouldComponentUpdate nextProps:{}------nextState:{"randomData":18,"hasChild":false}
father componentWillUpdate
father render
child componentWillUnmount
father componentDidUpdate

点击show按钮,
页面变化如下


image.png

控制台输入结果如下

father shouldComponentUpdate nextProps:{}------nextState:{"randomData":18,"hasChild":true}
father componentWillUpdate
father render
child constructor
child componentWillMount
child render
child componentDidMount
father componentDidUpdate

由控制台输出的内容顺序可以理解到React组件各个生命周期钩子函数的执行顺序

下图可以更好地理解组件的生命周期


React生命周期.png

相关文章

  • react简介

    第一单元(react简介) 课程目标 理解react这个框架在前端开发中的地位 理解react诞生的原因和意义(r...

  • 理解React

    React v16.4.0 一、理解优点 1、虚拟DOM2、合成事件(SyntheticEvent) 1、虚拟DO...

  • react理解

    1.何为react 什么是react?react是一个用于构建用户界面的JS库; react能干什么?通过组件化的...

  • 认知React Fiber

    上次写了react整体框架的理解,这次想写写看对于新版React的新的React Fiber的实现。 在React...

  • 彻底理解React 之React SSR、React服务端渲染,

    彻底理解React 之React SSR、React服务端渲染,教你从零搭建配置 https://www.jian...

  • React Native - 01 - Hello World!

    React Native就像React,但它使用本地组件而不是Web组件作为构建块。因此,要理解React Nat...

  • 交接文档

    参考内容 ReactReact 入门实例教程深入理解React react-nativereact-nativer...

  • react-router/react-router-dom

    最近看了react-router 源码,对react-router有了更深的理解,下面写点东西备忘:react-r...

  • react的部分考点

    1. 对react的理解 react是什么 用于构建用户界面的 JavaScript 库 react能干什么 可以...

  • react-redux性能优化之reselect

    在React-redux深入理解中,我们知道了 react-redux 是如何将 React 和 Redux 进行...

网友评论

    本文标题:理解React

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