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 相关文章推荐
比Jquery的document.ready更快的方法
Apr 28 Javascript
js通过location.search来获取页面传来的参数
Sep 11 Javascript
jquery结婚电子请柬特效源码分享
Aug 21 Javascript
js实现简单计算器
Nov 22 Javascript
基于jQuery插件实现点击小图显示大图效果
May 11 Javascript
js代码实现下拉菜单【推荐】
Dec 15 Javascript
Webpack打包慢问题的完美解决方法
Mar 16 Javascript
koa上传excel文件并解析的实现方法
Aug 09 Javascript
浅谈微信小程序flex布局基础
Sep 10 Javascript
更改BootStrap popover的默认样式及popover简单用法
Sep 13 Javascript
angularJs在多个控制器中共享服务数据的方法
Sep 30 Javascript
详解Vue3中对VDOM的改进
Apr 23 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
curl实现站外采集的方法和技巧
2014/01/31 PHP
教你识别简单的免查杀PHP后门
2015/09/13 PHP
PHP判断是否是微信打开还是浏览器打开的方法
2019/02/27 PHP
基于jquery的气泡提示效果
2010/05/31 Javascript
JS对象与json字符串格式转换实例
2014/10/28 Javascript
js进行表单验证实例分析
2015/02/10 Javascript
jquery实现兼容IE8的异步上传文件
2015/06/15 Javascript
Jquery $when done then的用法详解
2016/05/20 Javascript
JS新包管理工具yarn和npm的对比与使用入门
2016/12/09 Javascript
jQuery点击弹出层弹出模态框点击模态框消失代码分享
2017/01/21 Javascript
微信小程序 自动登陆PHP源码实例(源码下载)
2017/05/08 Javascript
深入浅出webpack之externals的使用
2017/12/04 Javascript
浅谈微信小程序之官方UI框架we-ui使用教程
2018/08/20 Javascript
vue.js实现二级菜单效果
2019/10/19 Javascript
[48:48]完美世界DOTA2联赛PWL S3 Magama vs GXR 第一场 12.19
2020/12/24 DOTA
python多线程扫描端口示例
2014/01/16 Python
使用Django简单编写一个XSS平台的方法步骤
2019/03/25 Python
详解python中的time和datetime的常用方法
2019/07/08 Python
python urllib爬虫模块使用解析
2019/09/05 Python
tensorflow实现测试时读取任意指定的check point的网络参数
2020/01/21 Python
python3 正则表达式基础廖雪峰
2020/03/25 Python
Python实现Canny及Hough算法代码实例解析
2020/08/06 Python
浅析Python requests 模块
2020/10/09 Python
Tory Burch英国官方网站:美国时尚生活品牌
2017/12/06 全球购物
Hunter Boots美国官方网站:赫特威灵顿雨靴
2018/06/16 全球购物
医学院学生的自我评价分享
2013/11/19 职场文书
绩效专员岗位职责
2013/12/02 职场文书
《雪地里的小画家》教学反思
2014/02/22 职场文书
2014年师德师风自我剖析材料
2014/09/27 职场文书
2015年基建工作总结范文
2015/05/23 职场文书
秋菊打官司观后感
2015/06/03 职场文书
公安忠诚教育心得体会
2016/01/23 职场文书
送给教师们,到底该如何写好教学反思?
2019/07/02 职场文书
php 获取音视频时长,PHP 利用getid3 获取音频文件时长等数据
2021/04/01 PHP
python获取字符串中的email
2022/03/31 Python