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 相关文章推荐
js 实现菜单上下显示附效果图
Nov 21 Javascript
理解Angular数据双向绑定
Jan 10 Javascript
JavaScript是如何实现继承的(六种方式)
Mar 31 Javascript
JS构造函数与原型prototype的区别介绍
Jul 04 Javascript
什么是JavaScript注入攻击?
Sep 14 Javascript
easyui导出excel无法弹出下载框的快速解决方法
Nov 10 Javascript
微信小程序 时间格式化(util.formatTime(new Date))详解
Nov 16 Javascript
Jquery Easyui进度条组件Progress使用详解(8)
Mar 26 Javascript
JS高仿抛物线加入购物车特效实现代码
Feb 20 Javascript
使用Vue如何写一个双向数据绑定(面试常见)
Apr 20 Javascript
vue实现全屏滚动效果(非fullpage.js)
Mar 07 Javascript
js+css实现扇形导航效果
Aug 18 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
今天你说520了吗?不仅有php表白书还有java表白神器
2016/05/20 PHP
javascript 学习之旅 (2)
2009/02/05 Javascript
js constructor的实际作用分析
2011/11/15 Javascript
Firefox中通过JavaScript复制数据到剪贴板(Copy to Clipboard 跨浏览器版)
2013/11/22 Javascript
js浮点数保留两位小数点示例代码(四舍五入)
2013/12/26 Javascript
禁止拷贝网页内容的js代码
2014/01/22 Javascript
Javascript中设置默认参数值示例
2014/09/11 Javascript
javascript 自定义回调函数示例代码
2014/09/26 Javascript
jQuery简单注册和禁用全局事件的方法
2016/07/25 Javascript
jQuery之动画ajax事件(实例讲解)
2017/07/18 jQuery
Vue resource中的GET与POST请求的实例代码
2017/07/21 Javascript
JQuery 选择器、DOM节点操作练习实例
2017/09/28 jQuery
vue 2.0 购物车小球抛物线的示例代码
2018/02/01 Javascript
Vue编写可显示周和月模式的日历 Vue自定义日历内容的显示
2019/06/26 Javascript
JavaScript中this的学习笔记及用法整理
2020/02/17 Javascript
微信小程序自定义navigationBar顶部导航栏适配所有机型(附完整案例)
2020/04/26 Javascript
bootstrapValidator表单校验、更改状态、新增、移除校验字段的实例代码
2020/05/19 Javascript
eslint+prettier统一代码风格的实现方法
2020/07/22 Javascript
[04:26]2014DOTA2国际邀请赛-Newbee顺利进入胜者组决赛 独家专访战神7
2014/07/19 DOTA
利用Python读取文件的四种不同方法比对
2017/05/18 Python
django模板语法学习之include示例详解
2017/12/17 Python
python分块读取大数据,避免内存不足的方法
2018/12/10 Python
Django后端按照日期查询的方法教程
2021/02/28 Python
IRO美国官网:法国服装品牌
2018/03/06 全球购物
丝芙兰意大利官方网站:Sephora.it
2019/12/13 全球购物
自我鉴定思想方面
2013/10/07 职场文书
本科毕业自我鉴定
2014/03/20 职场文书
航海技术专业毕业生推荐信
2014/07/09 职场文书
2014副局长群众路线对照检查材料思想汇报
2014/09/22 职场文书
2014年度工作总结报告
2014/12/15 职场文书
2015年教研工作总结
2015/05/23 职场文书
幼师自荐信范文(2016推荐篇)
2016/01/28 职场文书
golang中实现给gif、png、jpeg图片添加文字水印
2021/04/26 Golang
Redis 配置文件重要属性的具体使用
2021/05/20 Redis
Spring整合Mybatis的全过程
2021/06/28 Java/Android
nginx负载功能+nfs服务器功能解析
2022/02/28 Servers