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自适应IFrame高度(支持嵌套 兼容IE,ff,safafi,chrome)
Mar 28 Javascript
JQuery+JS实现仿百度搜索结果中关键字变色效果
Aug 02 Javascript
动态加载js和css(外部文件)
Apr 17 Javascript
解决jquery版本冲突的有效方法
Sep 02 Javascript
js简单网速测试方法完整实例
Dec 15 Javascript
JavaScript获取服务器时间的方法详解
Dec 11 Javascript
Nuxt.js实战详解
Jan 18 Javascript
Angular 组件之间的交互的示例代码
Mar 24 Javascript
Vue登录注册并保持登录状态的方法
Aug 17 Javascript
移动端滑动切换组件封装 vue-swiper-router实例详解
Nov 25 Javascript
详解微信小程序开发用户授权登陆
Apr 24 Javascript
详解Angular cli配置过程记录
Nov 07 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
Apache, PHP在Windows 9x/NT下的安装与配置 (一)
2006/10/09 PHP
php实现快速排序法函数代码
2012/08/27 PHP
PHP下使用CURL方式POST数据至API接口的代码
2013/02/14 PHP
Eclipse的PHP插件PHPEclipse安装和使用
2014/07/20 PHP
yii2控制器Controller Ajax操作示例
2016/07/23 PHP
PHP高并发和大流量解决方案整理
2021/03/09 PHP
TNC vs RR BO3 第一场 2.14
2021/03/10 DOTA
点击文章内容处弹出页面代码
2009/10/01 Javascript
js判断输入是否为数字的具体实例
2013/08/03 Javascript
JavaScript中创建对象和继承示例解读
2014/02/12 Javascript
详谈javascript异步编程
2016/02/21 Javascript
使用postMesssage()实现iframe跨域页面间的信息传递
2016/03/29 Javascript
jQuery插件实现文件上传功能(支持拖拽)
2020/08/27 Javascript
JavaScript常用代码书写规范的超全面总结
2016/09/11 Javascript
JSP防止网页刷新重复提交数据的几种方法
2016/11/19 Javascript
vue.js引入外部CSS样式和外部JS文件的方法
2019/01/06 Javascript
VUE 组件转换为微信小程序组件的方法
2019/11/06 Javascript
JavaScript实现Excel表格效果
2020/02/07 Javascript
Python遍历目录的4种方法实例介绍
2015/04/13 Python
使用Python程序抓取新浪在国内的所有IP的教程
2015/05/04 Python
Python获取系统默认字符编码的方法
2015/06/04 Python
python3学习笔记之多进程分布式小例子
2018/02/13 Python
Django migrations 默认目录修改的方法教程
2018/09/28 Python
python使用pipeline批量读写redis的方法
2019/02/18 Python
Python3.5 Json与pickle实现数据序列化与反序列化操作示例
2019/04/29 Python
python使用opencv实现马赛克效果示例
2019/09/28 Python
解决pycharm启动后总是不停的updating indices...indexing的问题
2019/11/27 Python
tensorflow的计算图总结
2020/01/12 Python
Laura Mercier官网:彩妆大师罗拉玛斯亚的化妆品牌
2018/01/04 全球购物
全球500多个机场的接送服务:Suntransfers
2019/06/03 全球购物
普天C++笔试题
2016/03/20 面试题
往来会计岗位职责
2013/12/19 职场文书
优秀教师个人总结
2015/02/11 职场文书
2015高考寄语集锦
2015/02/27 职场文书
三十年同学聚会感言
2015/07/30 职场文书
学校安全管理制度
2015/08/06 职场文书