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 相关文章推荐
自动检查并替换文本框内的字符
Jun 30 Javascript
基于OO的动画附加插件,可以实现弹跳、渐隐等动画效果 分享
Jun 24 Javascript
FireBug 调试JS入门教程 如何调试JS
Dec 23 Javascript
实例代码详解jquery.slides.js
Nov 16 Javascript
深入理解JS中的substr和substring
Apr 26 Javascript
使用vue.js开发时一些注意事项
Apr 27 Javascript
利用BootStrap的Carousel.js实现轮播图动画效果
Dec 21 Javascript
jQuery实现页面倒计时并刷新效果
Mar 13 Javascript
JS使用tofixed与round处理数据四舍五入的区别
Oct 25 Javascript
JS正则表达式验证端口范围(0-65535)
Jan 06 Javascript
JavaScript自定义超时API代码实例
Apr 30 Javascript
javascript条件式访问属性和箭头函数介绍
Nov 17 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
在php和MySql中计算时间差的方法
2011/04/22 PHP
php和mysql中uft-8中文编码乱码的几种解决办法
2012/04/19 PHP
php定界符
2014/06/19 PHP
Laravel 5.4向IoC容器中添加自定义类的方法示例
2017/08/15 PHP
基于laravel belongsTo使用详解
2019/10/18 PHP
jquery 子窗口操作父窗口的代码
2009/09/21 Javascript
测试你的JS的掌握程度的代码
2009/12/09 Javascript
Javascript Request获取请求参数如何实现
2012/11/28 Javascript
不用构造函数(Constructor)new关键字也能实现JavaScript的面向对象
2013/01/11 Javascript
javascript标签在页面中的位置探讨
2013/04/11 Javascript
jquery插件unobtrusive实现片段式加载
2015/06/15 Javascript
jQuery设置和获取select、checkbox、radio的选中值方法
2017/01/01 Javascript
微信小程序返回多级页面的实现方法
2017/10/27 Javascript
Vue.js组件props数据验证实现详解
2019/10/19 Javascript
OpenLayers3实现测量功能
2020/09/25 Javascript
[48:02]Ti4循环赛第三日 VG vs Liquid和NEWBEE vs DK
2014/07/12 DOTA
[57:47]Fnatic vs Winstrike 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
[01:01]2020完美高校联赛(秋)西安落幕
2021/03/11 DOTA
如何高效使用Python字典的方法详解
2017/08/31 Python
Django框架创建mysql连接与使用示例
2019/07/29 Python
Django 迁移、操作数据库的方法
2019/08/02 Python
python读写Excel表格的实例代码(简单实用)
2019/12/19 Python
python matplotlib中的subplot函数使用详解
2020/01/19 Python
解决TensorFlow GPU版出现OOM错误的问题
2020/02/03 Python
python爬虫开发之Request模块从安装到详细使用方法与实例全解
2020/03/09 Python
日本订房网站,预订日本星级酒店/温泉旅馆:Relux(支持中文)
2020/01/03 全球购物
语文教育专业推荐信范文
2013/11/25 职场文书
渡河少年教学反思
2014/02/12 职场文书
中学生关于梦想的演讲稿
2014/08/22 职场文书
副乡长民主生活会个人对照检查材料思想汇报
2014/10/01 职场文书
2014年法制宣传日活动方案
2014/11/02 职场文书
工作时间证明
2015/06/15 职场文书
爱国主义教育主题班会
2015/08/13 职场文书
Go语言-为什么返回值为接口类型,却返回结构体
2021/04/24 Golang
如何用JS实现网页瀑布流布局
2021/04/24 Javascript
Python循环之while无限迭代
2022/04/30 Python