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从头学起第三讲
Jul 06 Javascript
js与运算符和或运算符的妙用
Feb 14 Javascript
js 中将多个逗号替换为一个逗号的代码
Jun 07 Javascript
使用angular写一个hello world
Jan 23 Javascript
JavaScript的9种继承实现方式归纳
May 18 Javascript
JavaScript 最佳实践:帮你提升代码质量
Dec 03 Javascript
详解使用angularjs的ng-options时如何设置默认值(初始值)
Jul 18 Javascript
详解Angular中通过$location获取地址栏的参数
Aug 02 Javascript
jQuery选择器之基本过滤选择器用法实例分析
Feb 19 jQuery
深入了解js原型模式
May 30 Javascript
微信小程序 wx:for遍历循环使用实例解析
Sep 09 Javascript
代码解析React中setState同步和异步问题
Jun 03 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
Protoss热键控制
2020/03/14 星际争霸
PHP实时显示输出
2008/10/02 PHP
PHP面向接口编程 耦合设计模式 简单范例
2011/03/23 PHP
php笔记之:php数组相关函数的使用
2013/04/26 PHP
探讨fckeditor在Php中的配置详解
2013/06/08 PHP
使用PHP curl模拟浏览器抓取网站信息
2013/10/28 PHP
php实现mysql数据库连接操作及用户管理
2015/11/08 PHP
PHP Cookei记录用户历史浏览信息的代码
2016/02/03 PHP
thinkPHP实现MemCache分布式缓存功能
2016/03/23 PHP
PHPCMS手机站伪静态设置详细教程
2017/02/06 PHP
获取当前网页document.url location.href区别总结
2008/05/10 Javascript
ajax 缓存 问题 requestheader
2010/08/01 Javascript
javascript event 事件解析
2011/01/31 Javascript
js监听键盘事件示例代码
2013/07/26 Javascript
window.onload和$(function(){})的区别介绍
2013/10/30 Javascript
JS连连看源码完美注释版(推荐)
2013/12/09 Javascript
jquery form表单序列化为对象的示例代码
2014/03/05 Javascript
AngularJS基础 ng-mouseover 指令简单示例
2016/08/02 Javascript
BootStrop前端框架入门教程详解
2016/12/25 Javascript
js基于FileSaver.js 浏览器导出Excel文件的示例
2017/08/15 Javascript
VueJS 集成 Medium Editor的示例代码 (自定义编辑器按钮)
2017/08/24 Javascript
Angular客户端请求Rest服务跨域问题的解决方法
2017/09/19 Javascript
微信小程序实现animation动画
2018/01/26 Javascript
关于vue中watch检测到不到对象属性的变化的解决方法
2018/02/08 Javascript
JS 中可以提升幸福度的小技巧(可以识别更多另类写法)
2018/07/28 Javascript
利用weixin-java-miniapp生成小程序码并直接返回图片文件流的方法
2019/03/29 Javascript
JavaScript函数柯里化实现原理及过程
2020/12/02 Javascript
python使用xlrd模块读取xlsx文件中的ip方法
2019/01/11 Python
python实现五子棋小程序
2019/06/18 Python
Python基于class()实现面向对象原理详解
2020/03/26 Python
*p++ 自增p 还是p所指向的变量
2016/07/16 面试题
学习新党章思想汇报
2014/01/09 职场文书
创业计划书之寿司
2019/07/19 职场文书
总结Java对象被序列化的两种方法
2021/06/30 Java/Android
纯CSS如何禁止用户复制网页的内容
2021/11/01 HTML / CSS
Java Spring Boot 正确读取配置文件中的属性的值
2022/04/20 Java/Android