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对象和DOM对象的相互转化实现代码
Mar 02 Javascript
为超链接加上disabled后的故事
Dec 10 Javascript
extjs中form与grid交互数据(record)的方法
Aug 29 Javascript
基于豆瓣API+Angular开发的web App
Jan 02 Javascript
浅谈javascript中onbeforeunload与onunload事件
Dec 10 Javascript
详解AngularJS如何实现跨域请求
Aug 22 Javascript
Vue.js 单页面多路由区域操作的实例详解
Jul 17 Javascript
用最简单的方法判断JavaScript中this的指向(推荐)
Sep 04 Javascript
解决Jquery下拉框数据动态获取的问题
Jan 25 jQuery
详解ES6中的 Set Map 数据结构学习总结
Nov 06 Javascript
Node.js 实现抢票小工具 & 短信通知提醒功能
Oct 22 Javascript
Vue使用vue-draggable 插件在不同列表之间拖拽功能
Mar 12 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用数组返回无限分类的列表数据的代码
2010/08/08 PHP
PHP的autoload机制的实现解析
2012/09/15 PHP
跟我学Laravel之配置Laravel
2014/10/15 PHP
Yii2.0高级框架数据库增删改查的一些操作
2015/11/16 PHP
php实现常见图片格式的水印和缩略图制作(面向对象)
2016/06/15 PHP
php常用数组函数实例小结
2016/12/29 PHP
PHP页面静态化――纯静态与伪静态用法详解
2020/06/05 PHP
javascript 学习笔记(onchange等)
2010/11/14 Javascript
提取字符串中年月日的函数代码
2013/11/05 Javascript
JS 数字转换研究总结
2013/12/26 Javascript
Javascript中对象继承的实现小例
2014/05/12 Javascript
jQuery 删除/替换DOM元素的几种方式
2014/05/20 Javascript
Javascript中的call()方法介绍
2015/03/15 Javascript
jQuery中 attr() 方法使用小结
2015/05/03 Javascript
JS实现具备延时功能的滑动门菜单效果
2015/09/17 Javascript
Bootstrap安装环境配置教程分享
2016/05/27 Javascript
jQuery实现立体式数字动态增加(animate方法)
2016/12/21 Javascript
js实现简单的计算器功能
2017/01/16 Javascript
微信小程序开发之map地图实现教程
2017/06/08 Javascript
NodeJs项目中关闭ESLint的方法
2018/08/09 NodeJs
JS学习笔记之闭包小案例分析
2019/05/29 Javascript
React+EggJs实现断点续传的示例代码
2020/07/07 Javascript
[49:08]完美世界DOTA2联赛PWL S2 LBZS vs FTD.C 第一场 11.27
2020/12/01 DOTA
使用Python读写及压缩和解压缩文件的示例
2016/07/08 Python
用yum安装MySQLdb模块的步骤方法
2016/12/15 Python
python生成不重复随机数和对list乱序的解决方法
2018/04/09 Python
Python时间和字符串转换操作实例分析
2019/03/16 Python
详解Numpy数组转置的三种方法T、transpose、swapaxes
2019/05/27 Python
Python Matplotlib 基于networkx画关系网络图
2019/07/10 Python
Python 如何批量更新已安装的库
2020/05/26 Python
html5 canvas 使用示例
2010/10/22 HTML / CSS
html5拖曳操作 HTML5实现网页元素的拖放操作
2013/01/02 HTML / CSS
惠普墨西哥官方商店:HP墨西哥
2016/12/01 全球购物
铲车司机岗位职责
2014/03/15 职场文书
黄金搭档广告词
2014/03/21 职场文书
德劲DE1102数字调谐收音机机评
2022/04/07 无线电