React 组件渲染和更新的实现代码示例


Posted in Javascript onFebruary 21, 2019

最近一直写React,慢慢就对里面的一些实现很好奇。最好奇的就是自定义标签的实现和this.setState的实现。这里不分析JSX是如何解析的,所有组件都用ES5方式编写。

组件渲染

渲染时候,我们会调用render方法。类似下面这样:

var SayHi = React.createClass({
 getInitialState: function() {
  return {verb: 'say:'};
 },
 componentWillMount: function() {
  console.log('I will mount');
 },
 componentDidMount: function() {
  console.log('I have mounted');
 },
 render: function() {
  return React.createElement("div", null,this.state.verb, "Hello ", this.props.name);
 }
});

React.render(React.createElement(SayHi, {name: "Cynthia"}), document.getElementById("container"));

结果:

页面打印:
say: Hello Cynthia
控制台打印:
I will mount
I have mounted

React 组件渲染和更新的实现代码示例

这是我画的React对象上的一些属性和方法。

当调用render方法时,render会去调用一个map方法,根据传入参数的不同,把被render的对象分为以下三类:
* 文本
* 原生
* 自定义标签

文本

对于文本,React会实例化一个文本节点的对象,并且调用该对象的mount方法。在这个mount方法中,把文本放到一个span中,调用容器组件的innerHTML,进行渲染。

原生标签

对于原生标签,React会实例化一个处理原生标签的对象,并且调用该对象的mount方法。在这个mount方法中,拼接一个字符串,并且不断递归上面的map方法,最后把拼接好的字符串放到容器组件的innerHTML中,进行渲染。

自定义标签

这个应该是大家最好奇的。自定义标签虽然叫标签,其实就是一个类。实例化一个处理自定义标签的对象后,首先React会处理自定义标签的生命周期方法,然后再次递归调用子组件的render方法进而调用map方法,直至把自定义标签分解为前两种标签。

更新

首先,我们统一一下认识。在React里调用this.setState()会使得组件更新,调用this.state = {}只会更改本组件的状态,但是不会使得组件更新。

如果我要更新一个组件,我会这样写。

var SayHi = React.createClass({
 getInitialState: function() {
  return {verb: 'say:'};
 },
 componentWillMount: function() {
  console.log('I will mount');
 },
 componentDidMount: function() {
  console.log('I have mounted');
 },
 changeVerb: function(){
  this.setState({verb: 'write:'});
 }
 render: function() {
  return React.createElement("div", this.changeVerb.bind(this),this.state.verb, "Hello ", this.props.name);
 }
});

React.render(React.createElement(SayHi, {name: "Cynthia"}), document.getElementById("container"));

执行结果:

页面打印:
say: Hello Cynthia
点击文本,页面内容更新成:
write: Hello Cynthia

与更新相关的属性和方法如下:

React 组件渲染和更新的实现代码示例

在调用this.setState()以后,也是调用了一个map方法,根据传入参数不同,依然把要更新的标签分为文本、原生标签、自定义标签三类。具体处理过程如下。

文本

文本节点处理很简单,判断要更新后的文本与当前文本是否===,不是全等就删除原来文本,插入新文本。

自定义标签

对于自定义标签,首先根据对象的引用、key是否相同,判断是否需要更新。如果需要更新,就继续调用上述map方法进行子组件的更新。又是一个递归。但是注意,这里的map方法和渲染部分的map方法不是一个方法哟。

原生标签

对于原生标签,首先更新组件的属性,然后update子树,用diff算法来比较新的子树与目前标签的子树的不同,形成一个差异树,然后用patch方法,把这个差异树更新到真正的DOM树上。

总结

很复杂的过程,让我用流水账写了一遍。没能道出其中精华。以后继续探索,写的详细一些。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript 高效运行代码分析
Mar 18 Javascript
基于jquery完美拖拽,可返回拖动轨迹
Mar 29 Javascript
javascript自动改变文字大小和颜色的效果的小例子
Aug 02 Javascript
jQuery动画效果-slideUp slideDown上下滑动示例代码
Aug 28 Javascript
jQuery检测返回值的数据类型
Jul 13 Javascript
浅析Javascript中bind()方法的使用与实现
Apr 29 Javascript
前端实现文件的断点续传(前端文件提交+后端PHP文件接收)
Nov 04 Javascript
详解JS中的this、apply、call、bind(经典面试题)
Sep 19 Javascript
Angular网络请求的封装方法
May 22 Javascript
vue数组对象排序的实现代码
Jun 20 Javascript
JavaScript 中判断变量是否为数字的示例代码
Oct 22 Javascript
JS如何监听div的resize事件详解
Dec 03 Javascript
vue图片上传本地预览组件使用详解
Feb 20 #Javascript
Vue 后台管理类项目兼容IE9+的方法示例
Feb 20 #Javascript
浅谈小程序 setData学问多
Feb 20 #Javascript
9102年webpack4搭建vue项目的方法步骤
Feb 20 #Javascript
微信小程序五子棋游戏AI实现方法【附demo源码下载】
Feb 20 #Javascript
解决element ui select下拉框不回显数据问题的解决
Feb 20 #Javascript
微信小程序五子棋游戏的悔棋实现方法【附demo源码下载】
Feb 20 #Javascript
You might like
全国FM电台频率大全 - 24 贵州省
2020/03/11 无线电
php 如何获取文件的后缀名
2016/06/05 PHP
Linux下快速搭建php开发环境
2017/03/13 PHP
通过js脚本复制网页上的一个表格的不错实现方法
2006/12/29 Javascript
表头固定(利用jquery实现原理介绍)
2012/11/08 Javascript
JavaScript修改css样式style动态改变元素样式
2013/12/16 Javascript
NodeJS学习笔记之Connect中间件模块(二)
2015/01/27 NodeJs
JS+CSS实现简易的滑动门效果代码
2015/09/24 Javascript
ECharts仪表盘实例代码(附源码下载)
2016/02/18 Javascript
jquery根据一个值来选中select下的option实例代码
2016/08/29 Javascript
详解vue之页面缓存问题(基于2.0)
2017/01/10 Javascript
Ajax异步文件上传与NodeJS express服务端处理
2017/04/01 NodeJs
小发现之浅谈location.search与location.hash的问题
2017/06/23 Javascript
详解用vue编写弹出框组件
2017/07/04 Javascript
angularjs实现天气预报功能
2020/06/16 Javascript
node和vue实现商城用户地址模块
2018/12/05 Javascript
微信小程序实现下拉框功能
2019/07/16 Javascript
如何在微信小程序中存setStorage
2019/12/13 Javascript
原生js实现碰撞检测
2020/03/12 Javascript
Openlayers3实现车辆轨迹回放功能
2020/09/29 Javascript
js调用网络摄像头的方法
2020/12/05 Javascript
NodeJS和浏览器中this关键字的不同之处
2021/03/03 NodeJs
python类中super()和__init__()的区别
2016/10/18 Python
Python 基础教程之str和repr的详解
2017/08/20 Python
python中文件变化监控示例(watchdog)
2017/10/16 Python
Python程序员面试题 你必须提前准备!(答案及解析)
2018/01/23 Python
python获取代码运行时间的实例代码
2018/06/11 Python
在自动化中用python实现键盘操作的方法详解
2019/07/19 Python
详解Django admin高级用法
2019/11/06 Python
将python安装信息加入注册表的示例
2019/11/20 Python
解决Tensorflow 使用时cpu编译不支持警告的问题
2020/02/03 Python
python 中不同包 类 方法 之间的调用详解
2020/03/09 Python
python 实现图片批量压缩的示例
2020/12/18 Python
迪奥美国官网:Dior美国
2019/12/07 全球购物
小学三八妇女节活动方案
2014/03/16 职场文书
2016教师党员学习心得体会
2016/01/21 职场文书