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 MD4
Dec 20 Javascript
可缩放Reloaded-一个针对可缩放元素的复用组件
Mar 10 Javascript
JS实现在Repeater控件中创建可隐藏区域的代码
Sep 16 Javascript
JS隐藏参数post传值实例
Apr 18 Javascript
你必须知道的JavaScript 中字符串连接的性能的一些问题
May 07 Javascript
JavaScript中的运算符种类及其规则介绍
Sep 26 Javascript
浅谈js 闭包引起的内存泄露问题
Jun 22 Javascript
WordPress中利用AJAX异步获取评论用户头像的方法
Jan 08 Javascript
Vue中的数据监听和数据交互案例解析
Jul 12 Javascript
详解VueJS应用中管理用户权限
Feb 02 Javascript
jQuery内容选择器与表单选择器实例分析
Jun 28 jQuery
layui button 按钮弹出提示窗口,确定才进行的方法
Sep 06 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插件 Simple HTML DOM 用DOM方式处理HTML
2013/07/01 PHP
php实现数据库的增删改查
2017/02/26 PHP
用showModalDialog弹出页面后,提交表单总是弹出一个新窗口
2009/07/18 Javascript
jQuery之浮动窗口实现代码(两种方法)
2010/09/08 Javascript
理解Javascript_10_对象模型
2010/10/16 Javascript
Jquery Change与bind事件代码
2011/09/29 Javascript
jquery 列表双向选择器之改进版
2013/08/09 Javascript
javascript事件冒泡实例分析
2015/05/13 Javascript
JavaScript文档碎片操作实例分析
2015/12/12 Javascript
微信+angularJS的SPA应用中用router进行页面跳转,jssdk校验失败问题解决
2016/09/09 Javascript
Bootstrap面板学习使用
2017/02/09 Javascript
js实现倒计时关键代码
2017/05/05 Javascript
webpack配置打包后图片路径出错的解决
2018/04/26 Javascript
Vue+Jwt+SpringBoot+Ldap完成登录认证的示例代码
2018/05/21 Javascript
layui实现table加载的示例代码
2018/08/14 Javascript
微信{"errcode":48001,"errmsg":"api unauthorized, hints: [ req_id: 1QoCla0699ns81 ]"}
2018/10/12 Javascript
ios中视频的最后一桢问题解决
2019/05/14 Javascript
p5.js临摹动态图形实现方法详解
2019/10/23 Javascript
vue基于v-charts封装双向条形图的实现代码
2019/12/09 Javascript
在 Vue 中编写 SVG 图标组件的方法
2020/02/24 Javascript
微信小程序实现录制、试听、上传音频功能(带波形图)
2020/02/27 Javascript
vue使用nprogress加载路由进度条的方法
2020/06/04 Javascript
vue实现图片按比例缩放问题操作
2020/08/11 Javascript
[48:21]林俊杰圣堂刺客超神杀戮秀
2014/10/29 DOTA
python 字典(dict)遍历的四种方法性能测试报告
2014/06/25 Python
matplotlib 输出保存指定尺寸的图片方法
2018/05/24 Python
Tensorflow实现在训练好的模型上进行测试
2020/01/20 Python
快速解决Django关闭Debug模式无法加载media图片与static静态文件
2020/04/07 Python
Python3与fastdfs分布式文件系统如何实现交互
2020/06/23 Python
使用python批量修改XML文件中图像的depth值
2020/07/22 Python
html5 Canvas画图教程(9)—canvas中画出矩形和圆形
2013/01/09 HTML / CSS
什么是Remote Module
2016/06/10 面试题
档案接收函
2014/01/13 职场文书
讲文明树新风公益广告宣传方案
2014/02/25 职场文书
个人授权委托书模板
2014/09/14 职场文书
VUE中的v-if与v-show区别介绍
2022/03/13 Vue.js