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 相关文章推荐
Mootools 1.2教程(3) 数组使用简介
Sep 14 Javascript
js实现的日期操作类DateTime函数代码
Mar 16 Javascript
JQuery实现简单验证码提示解决方案
Dec 20 Javascript
JavaScript实现关键字高亮功能
Nov 12 Javascript
jQuery插件实现适用于移动端的地址选择器
Feb 18 Javascript
jQuery控制div实现随滚动条滚动效果
Jun 07 Javascript
javascript设计模式之module(模块)模式
Aug 19 Javascript
基于Vue2.0的分页组件
Mar 16 Javascript
基于 Vue.js 2.0 酷炫自适应背景视频登录页面实现方式
Jan 17 Javascript
js array数组对象操作方法汇总
Mar 18 Javascript
教你完全理解ReentrantLock重入锁
Jun 03 Javascript
Vue 电商后台管理项目阶段性总结(推荐)
Aug 22 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
一个目录遍历函数
2006/10/09 PHP
创建配置文件 用PHP写出自己的BLOG系统 2
2010/04/12 PHP
php学习之运算符相关概念
2011/06/09 PHP
解析coreseek for sphinx的使用
2013/06/21 PHP
PHP中copy on write写时复制机制介绍
2014/05/13 PHP
php基于base64解码图片与加密图片还原实例
2014/11/03 PHP
PHP中一些可以替代正则表达式函数的字符串操作函数
2014/11/17 PHP
PHP图片处理之使用imagecopyresampled函数实现图片缩放例子
2014/11/19 PHP
php使用Session和文件统计在线人数
2015/07/04 PHP
yii2.0整合阿里云oss的示例代码
2017/09/19 PHP
jQuery 性能优化指南(3)
2009/05/21 Javascript
使用js判断数组中是否包含某一元素(类似于php中的in_array())
2013/12/12 Javascript
javascript中的取反再取反~~没有意义
2014/04/06 Javascript
jQuery实现TAB风格的全国省份城市滑动切换效果代码
2015/08/24 Javascript
jQuery zclip插件实现跨浏览器复制功能
2015/11/02 Javascript
jQuery禁用键盘后退屏蔽F5刷新及禁用右键单击
2016/01/22 Javascript
JavaScript数组合并的多种方法
2016/05/22 Javascript
React-Native中禁用Navigator手势返回的示例代码
2017/09/09 Javascript
Javascript中弹窗confirm与prompt的区别
2018/10/26 Javascript
layui给下拉框、按钮状态、时间赋初始值的方法
2019/09/10 Javascript
基于element-ui对话框el-dialog初始化的校验问题解决
2020/09/11 Javascript
Python中的类学习笔记
2014/09/23 Python
Python实现比较扑克牌大小程序代码示例
2017/12/06 Python
python 编写简单网页服务器的实例
2018/06/01 Python
python代码如何实现余弦相似性计算
2020/02/09 Python
Pycharm内置终端及远程SSH工具的使用教程图文详解
2020/03/19 Python
python super()函数的基本使用
2020/09/10 Python
用CSS3实现背景渐变的方法
2015/07/14 HTML / CSS
欧洲最大的美妆零售网站:Feelunique
2017/01/14 全球购物
控制工程专业个人求职信
2013/09/25 职场文书
商业活动邀请函
2014/02/04 职场文书
志愿者服务感言
2014/02/27 职场文书
2014年村官工作总结
2014/11/24 职场文书
工作自我推荐信范文
2015/03/25 职场文书
法制教育讲座心得体会
2016/01/14 职场文书
《三国志》赏析
2019/08/27 职场文书