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 相关文章推荐
走出JavaScript初学困境—js初学
Dec 29 Javascript
js实现同一页面多个不同运动效果的方法
Apr 10 Javascript
js实现各种复制到剪贴板的方法(分享)
Oct 27 Javascript
JavaScript 数据类型详解
Mar 13 Javascript
简单的Vue异步组件实例Demo
Dec 27 Javascript
JavaScript使用享元模式实现文件上传优化操作示例
Aug 07 Javascript
Jquery和CSS实现选择框重置按钮功能
Nov 08 jQuery
浅谈Vue服务端渲染框架Nuxt的那些事
Dec 21 Javascript
使用vue for时为什么要key【推荐】
Jul 11 Javascript
Layui 导航默认展开和菜单栏选中高亮设置的方法
Sep 04 Javascript
vue基本使用--refs获取组件或元素的实例
Nov 07 Javascript
taro 实现购物车逻辑的实例代码
Jun 05 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 执行系统命令的方法
2009/07/07 PHP
php addslashes及其他清除空格的方法是不安全的
2012/01/25 PHP
php无限分类且支持输出树状图的详细介绍
2013/06/19 PHP
WordPres对前端页面调试时的两个PHP函数使用小技巧
2015/12/22 PHP
PHP图像识别技术原理与实现
2016/10/27 PHP
PHP多进程编程之僵尸进程问题的理解
2017/10/15 PHP
PHP+Ajax实现的检测用户名功能简单示例
2019/02/12 PHP
JS数组的遍历方式for循环与for...in
2014/07/31 Javascript
基于javascript实现样式清新图片轮播特效
2016/03/30 Javascript
Bootstrap前端开发案例二
2016/06/17 Javascript
利用AngularJs实现京东首页轮播图效果
2016/09/08 Javascript
js利用clipboardData实现截屏粘贴功能
2016/10/12 Javascript
如何通过非数字与字符的方式实现PHP WebShell详解
2017/07/02 Javascript
JS实现静态页面搜索并高亮显示功能完整示例
2017/09/19 Javascript
浅谈super-vuex使用体验
2018/06/25 Javascript
vuejs点击class变化的实例
2018/09/05 Javascript
在Vue中使用axios请求拦截的实现方法
2018/10/25 Javascript
基于vue实现圆形菜单栏组件
2019/07/05 Javascript
node express使用HTML模板的方法示例
2019/08/22 Javascript
javascript的delete运算符知识点总结
2019/11/19 Javascript
解决vue字符串换行问题(绝对管用)
2020/08/06 Javascript
[00:44]TI7不朽珍藏III——军团指挥官不朽展示
2017/07/15 DOTA
天翼开放平台免费短信验证码接口使用实例
2013/12/18 Python
Python操作MySQL数据库的三种方法总结
2018/01/30 Python
python实现人人自动回复、抢沙发功能
2018/06/08 Python
Pycharm pyuic5实现将ui文件转为py文件,让UI界面成功显示
2020/04/08 Python
Python读写压缩文件的方法
2020/07/30 Python
Python基于opencv的简单图像轮廓形状识别(全网最简单最少代码)
2021/01/28 Python
canvas 橡皮筋式线条绘图应用方法
2019/02/13 HTML / CSS
Zalando Lounge瑞士:时尚与生活方式购物俱乐部
2020/03/12 全球购物
Traffic People官网:女式花裙、上衣和连身裤
2020/10/12 全球购物
Trench London官方网站:高级风衣和意大利皮夹克
2020/07/11 全球购物
解释下面关于J2EE的名词
2013/11/15 面试题
毕业设计致谢词
2015/05/14 职场文书
清明节主题班会
2015/08/14 职场文书
Redisson实现Redis分布式锁的几种方式
2021/08/07 Redis